[英]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进行计数,每次执行以下操作:
所以你真的得到输出012
。
在第二个示例中,流再次从0到9计数,每次执行以下操作:
如您所见,输出在映射之前,因此您得到结果0123456789
。 尝试切换peek
和map
调用。 然后你会得到你期望的输出。
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.