Java 8流查看和限制交互

时间:2014-09-26 11:32:35

标签: java java-8 java-stream

为什么在java 8中使用此代码:

IntStream.range(0, 10)
        .peek(System.out::print)
        .limit(3)
        .count();

输出:

012

我希望它输出0123456789,因为窥视优先于限制。

在我看来,因为这个事实更加奇特:

IntStream.range(0, 10)
        .peek(System.out::print)
        .map(x -> x * 2)
        .count();

按预期输出0123456789(不是02481012141618)。

P.S。:.count()这里仅用于消费流,它可以替换为其他任何东西

4 个答案:

答案 0 :(得分:16)

关于流的最重要的事情是它们本身不包含元素(如集合),但它们的工作方式类似于 lazily 评估的管道。这意味着在终端操作运行之前,不会评估构建流的语句(包括映射,过滤或其他)。

在第一个示例中,流尝试从0到9进行计数,每次执行以下操作:

  1. 打印出值
  2. 检查是否传递了3个值(如果是,终止)
  3. 所以你真的得到了输出012

    在第二个示例中,流再次从0到9计数,每次执行以下操作:

    1. 打印出值
    2. maping x to x * 2,从而将值的两倍转发到下一步
    3. 正如您所看到的那样,输出在映射之前,因此您得到结果0123456789。尝试切换peekmap来电。然后你会得到你期望的输出。

答案 1 :(得分:7)

来自docs

limit()short-circuiting stateful intermediate operation.

map()intermediate operation

再次从docs开始,limit()将从其收到的流中返回一个包含x值的流。

  

中间操作是短路的,如果在呈现无限输入时,它可能会产生有限的流。

答案 2 :(得分:4)

Stream被定义为进行延迟处理。因此,为了完成count()操作,不需要查看其他项目。否则,它会被破坏,因为limit(…)被定义为在有限时间内处理无限流的正确方法(通过不处理超过limit项)。

原则上,可以在不查看int值的情况下完成您的请求,因为操作链limit(3).count()不需要对先前操作进行任何处理(除了验证流是否至少有3个项目。

答案 3 :(得分:2)

Streams使用延迟评估,在终端操作运行之前,不执行中间操作,即 peek()。 例如,以下代码只打印 1 。实际上,只要流的第一个元素1到达终端操作, findAny(),流执行将结束。

Arrays.asList(1,2,3)
            .stream()
            .peek(System.out::print)
            .filter((n)->n<3)
            .findAny();

以下示例中的Viceversa将打印 123 。事实上,终端操作 noneMatch()需要评估流的所有元素,以确保与谓词不匹配: n&gt; 4 < / p>

Arrays.asList(1, 2, 3)
            .stream()
            .peek(System.out::print)
            .noneMatch(n -> n > 4);