整个sort()是否先发生,然后传递给filter()?
那么,这不是违反了流应该做的事情吗?
不,不是.看看documentation of the Stream IPA:
中间操作进一步分为无状态和
Stateful operations可能需要process到entire input before
producing a result.例如,一个人无法从中产生任何结果
这意味着sorted
知道之前遇到的所有元素,即stateful.但是map
和filter
不需要这些信息,它们是stateless和lazy,这些操作总是一次处理一个来自流源的元素.
从技术上讲,通过孤立地查看单个元素来对管道中的内容进行排序是不可能的.sorted
"一次"对all个元素进行操作,并将排序后的流分发给下一个操作.你可能会把sorted
想象成一个新的流源.
让我们看看下面的流,并分析它将如何处理:
Stream.of("foo", "bar", "Alice", "Bob", "Carol")
.filter(str -> !str.contains("r")) // lazy processing
.peek(System.out::println)
.map(String::toUpperCase) // lazy processing
.peek(System.out::println)
.sorted() // <--- all data is being dumped into memory
.peek(System.out::println)
.filter(str -> str.length() > 3) // lazy processing
.peek(System.out::println)
.findFirst(); // <--- the terminal operation
sorted
之前的操作filter
和map
将延迟地应用于流源的每个元素,并且仅在需要时apply.即filter将应用于"foo"
,它成功通过filter,并通过map操作进行转换.然后filter应用在"bar"
上,它不会达到map.然后轮到"Alice"
通过filter,然后map将在该字符串上执行.等等
请记住,sorted()
需要所有数据来完成其工作,因此first filter将对源中的所有元素执行,map将应用于通过过滤器的每个元素.
然后sorted()
操作将把流的所有内容转储到内存中,并对通过第一个过滤器的元素进行排序.
在sorting之后,所有元素将再次被lazily one at a time处理.因此,second filter将被应用到only once(尽管3
个元素已通过第一个过滤器并被排序)."Alice"
将通过second filter并到达将返回该字符串的终端操作findFirst()
.
看看peek()
make的调试输出,执行过程如上所述.