可能会出现问题Java8,甚至Java16,执行如下Stream操作Stream.of(1,2,3,4).skip(1).limit(2).peek(System.out::println).count();会跳过元素1,打印元素2和3,最终计数为2。我想大家对此应该没有异议。但是从Java17开始,再次执行上面的代码,跳过元素1,计数为2,等等……是不是少了什么?是的,没有打印元素2和3?从API使用的角度来看,这是不正常的。如果我调用一个方法,我肯定希望它执行,即使它可能会抛出异常,但这里什么也没有发生。是的,元素2和3不再打印了?此方法的存在主要是为了支持调试,您希望在元素流过管道中的某个点时查看元素。这是对Stream的peek(Consumer)方法的解释,大意是虽然我们可以在流中通过peek进行一些使用中间操作来消费元素的方法,但是胖哥也为此写过相关的文章。不过这个API的设计初衷并不是改变Stream中元素的中间状态,而是为了Debug,让你可以观察到管道中元素经过的点:Stream.of("one","two","three","four").filter(e->e.length()>3)//观察正在被规则过??滤的长度大于3的元素.peek(e->System.out.println("Filteredvalue:"+e).map(String::toUpperCase)//观察正在转换为大写的元素.peek(e->System.out.println("Mappedvalue:"+e)).collect(Collectors.toList());也就是说,使用peek()改变Stream元素是Debug中一个“副作用”的操作,在执行了跳过操作skip(n)和限长操作limit(n)之后,Stream流的大小已经被预测出来了,为了得到流的大小,不需要遍历流的元素,跳过遍历就不能再通过peek()查看元素了。允许流不执行具有的操作e对结果没有影响,例如对已经排序的流进行排序。这个操作的结果是已知的,不需要迭代元素,也不会影响结果,所以不迭代。所以它不具备peek的价值。我敢说会有一大批项目,甚至是优秀的开源项目,都会受到这种新机制的影响,而且胖哥在项目中也使用了图片。所以如果你看了这篇文章并使用peek()做了一些“副作用”的操作,你需要评估升级Java17的影响。资料来源JavaChampion、Jetbrains核心开发人员TagirValeev和OracleJava语言架构师BrianGoetz之间的技术讨论中提到了新机制。BrianGoetz那么JDK给的建议是什么尽量不要用count(),连Stream.collect(Collectors.counting())用的都少,如果要换元素,根据情况用map操作或者foreach操作.如果您在Java17发布20天后升级,请注意这一点。但老实说,peek()用起来非常爽。改成这样很可惜。我不知道你怎么想的。欢迎留言讨论。
