Java 8流peek API

32

我用Java 8的peek试了以下代码片段。

List<String> list = Arrays.asList("Bender", "Fry", "Leela");
list.stream().peek(System.out::println);

但是控制台上没有任何输出。如果我改成以下方式:

list.stream().peek(System.out::println).forEach(System.out::println);

我看到以下内容,输出了peek和foreach调用。

Bender
Bender
Fry
Fry
Leela
Leela

无论是 foreach 还是 peek 都使用了 (Consumer<? super T> action) 参数,那么为什么输出结果会不同呢?

4个回答

40
Javadoc提到:

中间操作返回一个新流。它们总是延迟的;执行像filter()这样的中间操作实际上不执行任何过滤,而是创建一个新流,该流在遍历时包含与给定谓词匹配的初始流的元素。管道源的遍历不会开始,直到执行管道的终端操作。

由于peek是一种中间操作,因此不起作用。应用类似于foreach的终端操作时,结果确实会被打印出来。

1
peek 作为一种中间操作什么也不做 - 为什么会调用一个完全没有作用的方法呢? - a better oliver
3
@zeroflagL,这是一种中间操作方法,这意味着它是惰性的。除非对它执行终端操作以执行某些计算,否则它不会执行任何操作。据我所读,peek在你调试某个终端操作并想要在应用该终端操作之前找出先前状态的样子时特别有用。在这种情况下,您可以使用peek打印流的元素。 - Neo
6
不做事和懒惰是有区别的。此外,peek立即返回一个新的流,这也不是什么都没有做。 - a better oliver
我的评论(以及原始问题)更多地涉及其中指定的操作的执行... - Neo

6

peek的文档说:

返回一个流,其中包含此流的元素,并在从生成的流中使用元素时执行提供的操作。这是一种中间操作。

因此,您必须对结果流进行某些操作,以使System.out.println有所作为。


6
从关于peek方法的Stream文档中得知:
...在结果流中从每个元素被消耗时执行提供的操作。

0

Java-8中的流是惰性的,此外,如果在流中有两个链式操作紧挨着,那么第二个操作会在第一个操作处理完一个数据单元后立即开始(前提是在流中有终端操作)。

这就是为什么你可以看到重复的名称字符串被输出的原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接