如果你使用了这个Stream流操作,升级Java17有可能会出问题

开发 后端
从 API 使用的角度来看,这不太正常。如果我调用一个方法,我肯定希望它能够执行,即使它可能抛出一个异常,但是在这里却什么也没发生。

 [[419797]]

在Java 8 中,甚至到Java 16 中执行下面的Stream流操作

  1. Stream.of(1, 2, 3, 4) 
  2.           .skip(1) 
  3.           .limit(2) 
  4.           .peek(System.out::println) 
  5.           .count(); 

都会跳过元素1,打印元素2以及3,最终计数为2,我想大家对此应该都没有异议。

但是从Java 17 开始,再次执行上面的代码,跳过元素1,计数为2。等等…… 是不是少执行了点什么?

是的,不打印元素`2`和`3`了?

从 API 使用的角度来看,这不太正常。如果我调用一个方法,我肯定希望它能够执行,即使它可能抛出一个异常,但是在这里却什么也没发生。

  1. 是的,不打印元素`2`和`3`了? 

This method exists mainly to support debugging, where you want to see the elements as they flow past a certain point in a pipeline。

这是对Stream的peek(Consumer)方法的一个说明,大意是:虽然我们可以在流中通过peek执行一些利用中间操作消费元素的方法,胖哥为此还写过相关的文章。不过这个API的本意设计并不是为了改变Stream流中元素的中间态,而是为了Debug,为了让你能够观察到管道中的元素途经的点:

  1. Stream.of("one""two""three""four"
  2.          .filter(e -> e.length() > 3) 
  3.           // 观察正在被长度大于3规则过滤的元素 
  4.          .peek(e -> System.out.println("Filtered value: " + e)) 
  5.          .map(String::toUpperCase) 
  6.          // 观察正在被转大写的元素 
  7.          .peek(e -> System.out.println("Mapped value: " + e)) 
  8.          .collect(Collectors.toList()); 

也就是说使用peek()改变Stream元素是在Debug中“副作用”的一个操作。

Stream流的大小在执行跳过操作skip(n)和限制长度操作limit(n)后,流的大小长度是已经预知的,为了获得流的大小没必要去遍历流的元素,跳过了遍历就不能再通过peek()观察元素了。

允许流不执行对结果没有任何作用的操作,例如排序一个已经排序的流。这个操作的结果是已知的,不需要迭代元素,也不会影响结果,所以不迭代。所以不具有观察(peek)的价值。

我敢说会有大量的项目、甚至是优秀的开源项目会受到这个新机制的影响,胖哥也在项目中使用了图片。所以如果你看到这篇文章而且使用peek()做了一些“副作用”操作,就需要评估升级Java17带来的影响了。

消息来源

这一新机制是Java Champion、Jetbrains核心开发者塔吉尔·瓦列夫(Tagir Valeev)和Oracle Java 语言架构师Brian Goetz在一场技术讨论中提及的。

Brian Goetz

那么JDK给的建议是什么

尽量不使用count(),甚至Stream.collect(Collectors.counting())也少用,如果你想改变元素,根据情况使用map操作或者foreach操作。如果你在20天后Java17发布后进行升级一定要注意这一点。不过说实话peek()用着挺爽的,这么改的话有点可惜了,不知道你对此有什么看法,欢迎留言讨论。

责任编辑:武晓燕 来源: 码农小胖哥
相关推荐

2023-08-17 14:42:54

Redis分布式锁

2022-06-13 10:07:13

物联网开发物联网

2022-05-06 17:33:10

元宇宙现实问题沉迷风险

2021-09-08 22:29:46

Windows 11Windows微软

2024-01-04 08:38:21

Vue3API慎用

2019-05-27 13:42:33

Python编程语言代码

2020-11-16 07:03:59

Python内置

2020-12-16 05:54:18

充电宝信息安全

2021-09-09 11:24:09

微软Windows 11Windows

2021-10-11 20:52:20

微软Windows 11Windows

2010-03-22 16:27:57

Windows安全杀毒软件

2020-07-06 07:48:16

MySQL细节SQL

2018-07-10 10:45:00

规范Commit项目

2015-11-06 11:02:24

微信罗素生活

2018-05-10 11:50:13

Docker容器冷知识

2018-07-10 11:05:18

开发者技能命令

2021-06-06 16:52:11

工具函数JS

2019-11-13 16:20:28

jQueryJavaScript前端

2023-05-12 07:40:01

Java8API工具

2024-01-31 10:11:41

Redis内存
点赞
收藏

51CTO技术栈公众号