java流中的顺序保持

java流中的顺序保持,java,java-8,java-stream,Java,Java 8,Java Stream,我已经讨论过一些相关的问题,比如,输出元素的顺序对我来说还不是很清楚。因此,请澄清我的以下疑问 Integer[] intArray = {1, 2, 3, 4, 5, 6, 7, 8 }; List<Integer> listOfIntegers = new ArrayList<>(Arrays.asList(intArray)); listOfIntegers .paral

我已经讨论过一些相关的问题,比如,输出元素的顺序对我来说还不是很清楚。因此,请澄清我的以下疑问

 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 + " "));
Integer[]intArray={1,2,3,4,5,6,7,8};
整数列表=
新的ArrayList(Arrays.asList(intArray));
积分表
.parallelStream()
.无序
.forEachOrdered(e->System.out.print(e+);
我认为至少在理论上(或者根据java规范),它可以按1、2、3、4、5、6、7、8以外的随机顺序打印。我说得对吗

还有一个相关的问题-在什么执行点进行遭遇订单保存的决定?
更准确地说,是通过分析源头特征来评估整个河流管道顺序特征,中间操作和终端操作,甚至在执行开始之前?

一旦您选择了
无序
,则最终结果基本上可以以随机顺序进行。请注意,虽然没有要求它这样做,但事实上,您可能仍然会在输出中看到一些排序

forEachOrdered
保留“流”的遭遇顺序,因此如果您没有
.unordered()
,它将确保您以遭遇顺序查看元素。如果流已经
无序
,那么它就毫无意义,您最好使用
forEach


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

源的无序性质或通过
无序()明确发布订单合同
可能会影响所有后续管道阶段,除非它们引入的顺序只能在
已排序的
操作中发生

对于无状态的中间操作,如
filter
map
,没有任何区别,但是像
skip
limit
distinct
这样的操作可能会表现出不同的行为,这取决于之前的流状态是有序的还是无序的。显示了一个示例,说明以前的
unordered()
如何影响
distinct

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

提供一种打印流的特征并评估它们如何因附加其他操作而更改的方法

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

原则上,终端操作的无序性质可用于影响之前的阶段,但由于无状态中间操作无论如何都不会受到影响,
skip
limit
distinct
必须遵守之前的有序状态,如果存在,则是唯一可能受到影响的操作,已排序,如果后续操作不关心顺序,则该排序将过时

在当前的实现中,自Java8Update60以来,终端操作的无序性质不会影响前面阶段的行为。与以前的实施一样,这一更改错误地影响了
跳过
限制
。失去删除过时的排序步骤的机会并不被认为是一个问题,因为将
排序
与无序的后续操作链接在一起是一种极端情况。如果您想了解有关讨论的更多信息,请参阅,包括评论

所以

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
整个管道无序运行,只是因为源代码无序。有了一个有序的来源,它将是完全有序的


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

forEachOrdered
还保证不会同时调用使用者,因此可以说它将引入某种顺序,虽然消费者传递的
forEach
可能一次被多个线程调用,因此它确实是无序的,虽然
System.out.print
的内部同步也会在这种情况下强制执行一些命令…@Holger你能澄清一下相关问题吗?在什么时候决定保留遭遇命令?答案很好,比我的更深入:)