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

Pat*_* C. 67 java lambda peek java-8 java-9

我正在学习Java 8 lambda表达式的过程,并且想问一下peek我遇到的与函数接口中的方法有关的以下Java代码.

在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();
    }
}
Run Code Online (Sandbox Code Playgroud)

Eug*_*ene 61

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

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

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

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

  • @puhlen不,道德是,不要使用`peek`作为强制流执行副作用的方法(除了调试).如果要对每个流元素应用操作,请使用`forEach`. (27认同)
  • ...现在想象一个能够分析"谓词"代码的未来版本,以提前预测其结果,即对于特定的流管道是否永远或永远不会实现... (18认同)
  • 所以道德是,不要使用`count`作为强制流执行副作用的方法. (3认同)
  • @klaar“在一条链中完成它”并不是一个实际的目标。当您首先收集到列表并通过该结果列表上的“forEach”执行操作时,您不会注意到差异。除此之外,当这个问答已经说明了为什么 peek 根本不是替代方案时,说“没有 peek 的替代方案”是没有意义的。 (2认同)
  • 正如已经说过的,@ klaar,“试图将现有代码适合到单个Java流调用链中”是一个人为的目标。甚至重写代码以使用流也不是一个有用的目标,尤其是当此重写甚至不能产生干净的代码时。如前所述,您也不需要“窥视”,因为事后对结果集合执行检查时没有区别。特别是,这样的后续测试可以抛出这些检查的异常,这与`peek'不同。 (2认同)

Era*_*ran 61

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

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

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

API注意:

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

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

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

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

  • 值得注意的是[javadoc of count()](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#count--)中没有说同样的java 8. (7认同)
  • 来自[`Stream.peek`]的文档(https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#peek-java.util.function.Consumer- ) - >*如果流实现能够优化一些或所有元素的生成(例如像`findFirst`这样的短路操作,或者在`count`中描述的例子中),那么不会为这些元素调用.* (5认同)
  • @nullpointer也只是在Java 9文档中,尽管它总是暗示的. (3认同)