java Peek()真的很想看到元素流过管道中的某个点
用最简单的方式表达我的问题:
根据JavaDoc:
Peek()
method exists mainly to support debugging, where you want to see the elements as they flow past a certain point in a pipeline.
我有一根10米长的管子,距离3米和7米
从输入头我有两个标记[akapeek()
]用于检查/调试我的元素
现在从输入端开始,我给出1,2,3,4,5
的输入
在x=4米处,我有一个filter()
,它过滤所有小于等于^{
现在,根据Java文档,我应该能够在距离3
和7
米的地方看到我在管道中的输入发生了什么
距离3处(.peek()
)的标记1处的输出应该是1,2,3,4,5
不应该是??
而marker2处距离7处的输出显然应该是4,5
但实际情况并非如此,产量在第一市场(.peek())仅1,2,3
而在第二市场4,5
我为测试我的理论而执行的代码:
final List<Integer> IntList=
Stream.of(1, 2, 3, 4, 5)
.peek(it -> System.out.println("Before Filtering "+it)) // should print 1,2,3,4,5
.filter(it -> it >= 3)
.peek(it -> System.out.println("After Filtering: "+it)) //should print 4,5
.collect(Collectors.toList());
实际产量:
Before Filtering 1
Before Filtering 2
Before Filtering 3
After Filtering: 3
Before Filtering 4
After Filtering: 4
Before Filtering 5
After Filtering: 5
预期的输出(开发人员在阅读JavaDoc后应该怎么想(……主要是为了支持调试,在调试中,您希望看到元素在管道中流过某个点时……)
Before Filtering 1
Before Filtering 2
Before Filtering 3
Before Filtering 4
Before Filtering 5
After Filtering: 4
After Filtering: 5
如果.peek()
不仅仅是为了在管道中的特定点进行调试,那么它的定义是不明确的
很抱歉我讲了一个关于管道的故事,我想这样我就可以最好地解释我想问的问题了
# 1 楼答案
不可以。流可能会根据需要进行延迟评估,并且操作顺序没有严格定义,尤其是在
peek()
操作时。这使得streams API能够支持非常大的流,而不会严重浪费时间和内存,并且允许某些实现简化。特别是,在下一阶段开始之前,无需对管道的单个阶段进行全面评估假设根据您的假设,以下代码将是多么浪费:
这条流从100万个元素开始,到10个元素结束。如果我们充分评估每个阶段,我们的中间值将分别为100万、99995和10个元素
作为第二个示例,以下流不能一次评估一个阶段(因为
IntStream.generate
返回一个无限流):您的管道确实会通过第一个
peek
传递每个元素,然后只通过第二个peek
传递一个子集。但是,管道会以元素大调而不是阶段大调顺序执行此求值:它会对管道求值1,然后将其放到过滤器处,然后再求值2。一旦对管道求值3,它就会通过过滤器,从而执行peek语句,然后对4和5执行相同的操作