Java:流中的使用者接口无法按预期工作
我有两条语句,我希望它们“打印”相同的结果:
Arrays.stream("abc".split("")).forEach(System.out::println);//first
Arrays.stream("abc".split("")).peek(new Consumer<String>() {//second
@Override
public void accept(String s) {
System.out.println(s);//breakpoint
}
});
事实上,第一条语句将打印出来
a
b
c
好的,但是第二条语句不打印任何内容。我试图在IntelliJ中的“//breakpoint”行中设置一个断点,但没有成功
那么,在使用“Consumer”处理每个元素时,我应该如何将第二条语句更改为使用“peek”来创建新的流呢
非常感谢
# 1 楼答案
流操作分为中间
(Stream-producing)
操作和终端(value- or side-effect-producing)
操作。中间操作总是lazy
。因此,蒸汽一旦得到任何终端操作,就会开始执行操作管道。在第一种情况下forEach
是终端操作,因此执行流。但在第二个ca中,管道中的最后一个操作是peek()
,这不是终端操作# 2 楼答案
peek()
不是一个终端操作,它产生一个中间流。只有当流找到一个终端操作时,它才会被执行例如:如果您将
count()
终端操作添加到第二个流中,您将获得预期的输出注意——第一个流有一个输出,因为
forEach()
是一个终端操作# 3 楼答案
^{} ,正如API的javadocs中所述,主要是为了调试目的,不建议在peek操作期间对流执行任何更新操作
例如,您可以使用以下代码验证中间流状态及其最终结果:
一般来说,这个操作是一个中间操作不会被执行,除非在文档的Stream operations and pipelines部分提到的流上执行终端操作,这正是第一条语句将打印的原因
注意:尽管如其他一些答案所示,
peek
当它能够优化某些短路操作(如findFirst
等)的结果时,不会调用# 4 楼答案
peek()
不是终端操作,您需要添加任何终端操作以使peek工作,例如