在java流中遇到订单保存

我已经完成了相关的问题,例如如何确保java8流中的处理顺序? ,仍然对输出元素的排序并不完全清楚。 因此请澄清我的以下疑问。

Integer[] intArray = {1, 2, 3, 4, 5, 6, 7, 8 }; List listOfIntegers = new ArrayList(Arrays.asList(intArray)); listOfIntegers .parallelStream() .unordered() .forEachOrdered(e -> System.out.print(e + " ")); 

我认为至少在理论上(或根据java规范)它可以按照随机顺序打印,而不是1,2,3,4,5,6,7,8。我是否正确?

还有一个相关的问题 – 在执行的哪个阶段采取遭遇订单保留的决定? 更确切地说 – 即使在执行开始之前,通过查看源,中间操作和终端操作的特征来评估整个流管道ORDER特性?

源的无序性质或通过unordered()明确释放订单合同可能会影响所有后续流水线阶段,除非它们引入的订单只能在sorted操作中发生。

对于像filtermap这样的无状态中间操作,无论如何都没有区别,但是skiplimitdistinct可能会表现出不同的行为,具体取决于前一个流状态是有序还是无序。 这个答案显示了一个前一个unordered()可以如何影响distinct的例子。

请注意,原则上,在引入订单时sorted可能取决于前一阶段的有序状态,因为如果前一个流是无序的,它可能会使用不稳定的排序算法。

此答案提供了一种方法来打印流的特征,并评估它们由于附加另一个操作而发生的变化。

当您链接终端操作时,终端操作本身的无序性质或终端操作之前的最后阶段的无序状态可能足以为不尝试保留该顺序的终端操作选择算法。

原则上,终端操作的无序性质可用于影响先前的阶段,但由于无状态中间操作无论如何都不受影响而且skiplimitdistinct必须服从先前的有序状态(如果存在),唯一的操作可能是如果后续操作不关心订单,那么对受影响的文件进行sorted会变得过时。

在当前实现中,由于Java 8更新60,终端操作的无序性质不影响先前阶段的行为。 与以前的实现一样,这种更改已经错误地影响了skiplimit 。 没有机会消除过时的分类步骤并不是一个问题,因为链接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); // may print the remaining elements in arbitrary order 

流管道没有单一的有序或无序行为。

与…对比

 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); // would respect order if there was one 

整个管道无序运行,只是因为源是无序的。 使用有序的来源,它将完全订购。

因此,“ 即使在执行开始之前,通过查看源,中间操作和终端操作的特性来评估整个流管道ORDER特性的答案是什么? “是,是的,这是在开始实际处理之前完成的,通过选择适当的管道阶段算法,当有选择时,但这个过程不一定会导致整个管道的单一特征。

一旦您选择了unordered那么最终结果可以基本上以随机顺序通过。 请注意,虽然没有要求,但实际上您可能仍会在输出中看到一些排序。

forEachOrdered保留’stream’的遭遇顺序,所以如果你没有.unordered()那么它会确保你看到遇到顺序的元素。 如果流已经unordered那么它是没有意义的,你也可以使用forEach

换句话说, forEachOrdered在已排序的流中保留遭遇顺序。 它不进行任何排序或其他排序,但如果流已经unordered那么任何事情都可能发生。