Java 8与Java 9中的Stream.peek()方法

时间:2022-06-01 20:19:55

I am in the progress of learning through Java 8 lambda expressions and would like to ask about the following piece of Java code relating to the peek method in the function interface that I have come across.

我正在学习Java 8 lambda表达式,并想询问下面与我遇到的函数接口中的peek方法相关的Java代码。

On execution of the program on IDE, it gives no output. I was expecting it would give 2, 4, 6.

在IDE上执行程序时,它不提供输出。我原以为它会给2,4,6。

import java.util.Arrays;
import java.util.List;

public class Test_Q3 {

    public Test_Q3() {
    }

    public static void main(String[] args) {
        List<Integer> values = Arrays.asList(1, 2, 3);
        values.stream()
              .map(n -> n * 2)
              .peek(System.out::print)
              .count();
    }
}

2 个解决方案

#1


51  

I assume you are running this under Java 9? You are not altering the SIZED property of the stream, so there is no need to execute either map or peek at all.

我假设你在Java 9下运行它?您没有改变流的SIZED属性,因此根本不需要执行map或peek。

In other words all you care is about count as the final result, but in the meanwhile you do not alter the initial size of the List in any way (via filter for example or distinct) This is an optimization done in the Streams.

换句话说,你所关心的只是算作最终结果,但同时你不会以任何方式改变List的初始大小(例如通过过滤器或不同)这是在Streams中完成的优化。

Btw, even if you add a dummy filter this will show what you expect:

顺便说一句,即使你添加一个虚拟过滤器,这将显示你的期望:

values.stream ()
      .map(n -> n*2)
      .peek(System.out::print)
      .filter(x -> true)
      .count();

#2


52  

Here's some relevant quotes from the Javadoc of Stream interface:

以下是来自Javadoc of Stream接口的一些相关引用:

A stream implementation is permitted significant latitude in optimizing the computation of the result. For example, a stream implementation is free to elide operations (or entire stages) from a stream pipeline -- and therefore elide invocation of behavioral parameters -- if it can prove that it would not affect the result of the computation. This means that side-effects of behavioral parameters may not always be executed and should not be relied upon, unless otherwise specified (such as by the terminal operations forEach and forEachOrdered). (For a specific example of such an optimization, see the API note documented on the count() operation. For more detail, see the side-effects section of the stream package documentation.)

允许流实现在优化结果的计算方面具有显着的*度。例如,流实现可以*地从流管道中删除操作(或整个阶段) - 因此可以省略对行为参数的调用 - 如果它可以证明它不会影响计算结果。这意味着行为参数的副作用可能并不总是被执行,并且不应该被依赖,除非另有规定(例如通过forEach和forEachOrdered的终端操作)。 (有关此类优化的具体示例,请参阅count()操作中记录的API说明。有关更多详细信息,请参阅流包文档的副作用部分。)

And more specifically from the Javadoc of count() method:

更具体地说,来自count()方法的Javadoc:

API Note:

API注意:

An implementation may choose to not execute the stream pipeline (either sequentially or in parallel) if it is capable of computing the count directly from the stream source. In such cases no source elements will be traversed and no intermediate operations will be evaluated. Behavioral parameters with side-effects, which are strongly discouraged except for harmless cases such as debugging, may be affected. For example, consider the following stream:

如果实现可以直接从流源计算计数,则实现可以选择不执行流管道(顺序地或并行地)。在这种情况下,不会遍历任何源元素,也不会评估中间操作。除了诸如调试之类的无害情况之外,强烈不鼓励具有副作用的行为参数可能会受到影响。例如,请考虑以下流:

List<String> l = Arrays.asList("A", "B", "C", "D");
long count = l.stream().peek(System.out::println).count();

The number of elements covered by the stream source, a List, is known and the intermediate operation, peek, does not inject into or remove elements from the stream (as may be the case for flatMap or filter operations). Thus the count is the size of the List and there is no need to execute the pipeline and, as a side-effect, print out the list elements.

流源(List)所覆盖的元素数量是已知的,并且中间操作peek不会从流中注入或移除元素(对于flatMap或过滤操作可能是这种情况)。因此,count是List的大小,并且不需要执行管道,并且作为副作用,打印出list元素。

These quotes only appear on the Javadoc of Java 9, so it must be a new optimization.

这些引号仅出现在Java 9的Javadoc上,因此它必须是一个新的优化。

#1


51  

I assume you are running this under Java 9? You are not altering the SIZED property of the stream, so there is no need to execute either map or peek at all.

我假设你在Java 9下运行它?您没有改变流的SIZED属性,因此根本不需要执行map或peek。

In other words all you care is about count as the final result, but in the meanwhile you do not alter the initial size of the List in any way (via filter for example or distinct) This is an optimization done in the Streams.

换句话说,你所关心的只是算作最终结果,但同时你不会以任何方式改变List的初始大小(例如通过过滤器或不同)这是在Streams中完成的优化。

Btw, even if you add a dummy filter this will show what you expect:

顺便说一句,即使你添加一个虚拟过滤器,这将显示你的期望:

values.stream ()
      .map(n -> n*2)
      .peek(System.out::print)
      .filter(x -> true)
      .count();

#2


52  

Here's some relevant quotes from the Javadoc of Stream interface:

以下是来自Javadoc of Stream接口的一些相关引用:

A stream implementation is permitted significant latitude in optimizing the computation of the result. For example, a stream implementation is free to elide operations (or entire stages) from a stream pipeline -- and therefore elide invocation of behavioral parameters -- if it can prove that it would not affect the result of the computation. This means that side-effects of behavioral parameters may not always be executed and should not be relied upon, unless otherwise specified (such as by the terminal operations forEach and forEachOrdered). (For a specific example of such an optimization, see the API note documented on the count() operation. For more detail, see the side-effects section of the stream package documentation.)

允许流实现在优化结果的计算方面具有显着的*度。例如,流实现可以*地从流管道中删除操作(或整个阶段) - 因此可以省略对行为参数的调用 - 如果它可以证明它不会影响计算结果。这意味着行为参数的副作用可能并不总是被执行,并且不应该被依赖,除非另有规定(例如通过forEach和forEachOrdered的终端操作)。 (有关此类优化的具体示例,请参阅count()操作中记录的API说明。有关更多详细信息,请参阅流包文档的副作用部分。)

And more specifically from the Javadoc of count() method:

更具体地说,来自count()方法的Javadoc:

API Note:

API注意:

An implementation may choose to not execute the stream pipeline (either sequentially or in parallel) if it is capable of computing the count directly from the stream source. In such cases no source elements will be traversed and no intermediate operations will be evaluated. Behavioral parameters with side-effects, which are strongly discouraged except for harmless cases such as debugging, may be affected. For example, consider the following stream:

如果实现可以直接从流源计算计数,则实现可以选择不执行流管道(顺序地或并行地)。在这种情况下,不会遍历任何源元素,也不会评估中间操作。除了诸如调试之类的无害情况之外,强烈不鼓励具有副作用的行为参数可能会受到影响。例如,请考虑以下流:

List<String> l = Arrays.asList("A", "B", "C", "D");
long count = l.stream().peek(System.out::println).count();

The number of elements covered by the stream source, a List, is known and the intermediate operation, peek, does not inject into or remove elements from the stream (as may be the case for flatMap or filter operations). Thus the count is the size of the List and there is no need to execute the pipeline and, as a side-effect, print out the list elements.

流源(List)所覆盖的元素数量是已知的,并且中间操作peek不会从流中注入或移除元素(对于flatMap或过滤操作可能是这种情况)。因此,count是List的大小,并且不需要执行管道,并且作为副作用,打印出list元素。

These quotes only appear on the Javadoc of Java 9, so it must be a new optimization.

这些引号仅出现在Java 9的Javadoc上,因此它必须是一个新的优化。