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

Stream.peek() method in Java 8 vs Java 9

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

在 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();
    }
}

我假设你是运行这个下Java9?您没有更改流的 SIZED 属性,因此根本不需要执行 mappeek

换句话说,您只关心 count 作为最终结果,但与此同时,您不会更改 any[= 中 List 的初始大小25=] 方式(例如通过 filterdistinct)这是在 Streams 中完成的优化。

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

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

以下是 Stream 接口的 Java 文档中的一些相关引述:

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.)

更具体地说,来自 count() 方法的 Java 文档:

API Note:

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.

这些引用只出现在Java9的Java文档中,所以它必须是一个新的优化。