我认为在 scala 中这些方法工作正常但在 java9 dropWhile 中工作不同。
这里是 takeWhile 的例子
Stream.of("a", "b", "c", "de", "f", "g", "h")
.peek(System.out::println)
.takeWhile(s -> s.length() <= 1)
.collect(Collectors.toList());
输出很好: a, b, c, de, [a, b, c] 它不处理“de”之后的元素,因此它按预期工作
但是 dropWhile 的工作方式与我预期的不同:
Stream.of("a", "b", "c", "de", "f", "g", "h")
.peek(s -> System.out.print(s + ", "))
.dropWhile(s -> s.length() <= 1)
.collect(Collectors.toList());
输出是: a, b, c, de, f, g, h, [de, f, g, h]
所以它不会在“de”元素之后停止,它正在处理整个集合。
为什么要处理整个集合?我知道,它需要获取所有元素并将其收集到列表中,但它不应该在“de”元素之后停止处理吗?
最佳答案
看来,对于peek
的工作原理存在根本性的误解。它不与下一个后续链接操作相关联,如 dropWhile
,而是与它背后的整个 Stream 管道相关联。并且不区分“处理元素”和“取所有元素”。
所以简单的代码
Stream.of("a", "b", "c", "de", "f", "g", "h")
.peek(System.out::println)
.collect(Collectors.toList());
“获取所有元素”,但在它们从流源传递到收集器时打印它们。
在你的例子中,无论一个元素是传递给dropWhile
的谓词还是直接传递给Collector
,都没有区别,无论哪种情况,都会被报告通过放在 both 之前的 peek
操作。
如果你使用
Stream.of("a", "b", "c", "de", "f", "g", "h")
.dropWhile(s -> {
System.out.println("dropWhile: "+s);
return s.length() <= 1;
})
.peek(s -> System.out.println("collecting "+s))
.collect(Collectors.toList());
相反,它会打印
dropWhile: a
dropWhile: b
dropWhile: c
dropWhile: de
collecting de
collecting f
collecting g
collecting h
展示了 dropWhile
的谓词的评估如何在第一个未接受的元素之后停止,而向 Collector
的传输从该元素开始。
这与 takeWhile
不同,其中 both,谓词求值和收集器停止消耗元素,因此没有剩余的消费者,整个 Stream 管道可以停止迭代来源。
关于java - takeWhile, dropWhile 惰性 java9,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41601498/