繁体   English   中英

Java 8 stream 偷看和限制互动

[英]Java 8 stream peek and limit interaction

为什么这个代码在java 8:

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

输出:

012

我希望它是 output 0123456789 ,因为 peek 优先于限制。

在我看来,这更奇怪,因为:

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

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

PS:这里的.count .count()只是用来消费stream的,可以换成别的

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

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

  1. 打印出来的价值
  2. 检查是否传递了3个值(如果是,则终止)

所以你真的得到输出012

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

  1. 打印出来的价值
  2. maping x to x * 2,从而将值的两倍转发到下一步

如您所见,输出在映射之前,因此您得到结果0123456789 尝试切换peekmap调用。 然后你会得到你期望的输出。

来自文档

limit()是一种short-circuiting stateful intermediate operation.

map()是一个intermediate operation

再次从文档中 ,它本质上意味着limit()将从它收到的流返回一个带有x值的流。

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

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

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

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

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

在下面的例子中,Viceversa将被打印123 实际上,终端操作noneMatch()需要评估流的所有元素,以确保与谓词不匹配: n> 4

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

对于努力理解count方法如何不执行它之前的peek方法的未来读者,我想我添加了这个额外的注释:

根据 Java 9, count方法的Java 文档指出:

如果实现能够直接从 stream 源计算计数,则它可以选择不执行 stream 管道(顺序或并行)。

这意味着用count终止 stream 不再足以确保执行所有先前的步骤,例如peek

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM