源的无序性或通过 unordered()
显式释放顺序合同可能会影响所有后续的管道阶段,除非它们引入了一种只能通过 sorted
操作发生的排序。
对于像 filter
和 map
这样的状态中间操作,无论如何都没有区别,但像 skip
、limit
和 distinct
这样的操作,其行为可能会有所不同,具体取决于前一个流状态是有序还是无序。 这个答案 展示了一个例子,说明如何使 distinct
受到之前的 unordered()
的影响。
请注意,在原则上,sorted
虽然引入了一种顺序,但它可能取决于先前阶段的有序状态,因为如果之前的流是无序的,则可能使用不稳定的排序算法。
这个答案 提供了一种打印流特征并评估由于附加另一个操作而如何改变流特征的方法。
当您链接一个终端操作时,终端操作本身的无序性或终端操作之前的最后一个阶段的无序状态可能足以选择一个不试图保留顺序的算法来执行终端操作。
原则上,终端操作的无序性可能会影响先前的阶段,但是由于状态中间操作不受影响,而且 skip
、limit
和 distinct
必须遵守之前的有序状态(如果存在),因此唯一可能受到影响的操作是 sorted
,如果随后的操作无论如何都不关心顺序,则该操作将变得过时。
在当前实现中,自 Java 8 更新 60 以来,终端操作的无序性不会影响先前阶段的行为。这个改变是因为,在先前的实现中,它错误地影响了 skip
和 limit
。失去消除过时排序步骤的机会并没有被视为问题,因为链接具有无序的随后操作的 sort
是一种角落情况。如果您想了解相关讨论的更多信息,请参见 这个答案,包括评论。
因此,
list.stream() // List.stream() returns an ordered stream
.unordered() // releases order contract
.distinct() // for equal elements, it may pick an arbitrary one
.sorted() // re-introduces an order
.skip(1) // will skip the minimum element due to the order
.forEach(System.out::println)
有关流水线的有序或无序行为是不确定的。
相比之下,
hashSet.stream() // HashSet.stream() has no order (unless being a LinkedHashSet)
.filter(Objects::nonNull) // not affected by order
.distinct() // may use unorderedness, but has no effect anyway, as already distinct
.skip(1) // may skip an arbitrary element
.forEachOrdered(System.out::println)
整个流水线的执行顺序是无序的,因为源数据是无序的。如果源数据是有序的,那么整个流水线就是有序的。因此,“
在实际执行之前,是否通过查看源、中间操作和终端操作的特性来确定整个流媒体流水线的ORDER特性?”的答案是肯定的。在有选择的情况下,会选择适当的算法来处理流水线阶段,但这个过程不一定会导致整个流水线具有单一的特性。请注意,HTML标签应该被保留。