java流中遇到顺序保存

nan*_*itv 3 java java-8 java-stream

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

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

我认为至少在理论上(或根据 java 规范)它可以按比 1、2、3、4、5、6、7、8 的随机顺序打印。我说得对吗?

还有一个相关的问题——相遇顺序保留的决定是在什么执行点做出的?更准确地说 - 整个流管道 ORDER 特性的评估是否在执行开始之前通过源、中间操作和终端操作的特性完成?

Hol*_*ger 6

源的无序性质或订单合约通过的显式发布unordered()可能会影响所有后续管道阶段,除非它们引入了只能在sorted操作中发生的订单。

对于像filterand这样的无状态中间操作map,无论如何都没有区别,但是像skip, limitand这样的操作distinct可能会表现出不同的行为,具体取决于先前的流状态是有序还是无序。此答案显示了如何distinct受先前unordered().

请注意,原则上,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
Run Code Online (Sandbox Code Playgroud)

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

与...对比

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
Run Code Online (Sandbox Code Playgroud)

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

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

  • 很好的答案,比我的更深入:) (2认同)