遇到订单友好/不友好的终端操作与并行/顺序与有序/无序流

Fed*_*ner 8 java java-8 java-stream

这个问题的启发,我开始玩有序与无序流,并行与顺序流和终端操作,这些操作尊重遭遇顺序与不尊重它的终端操作.

在对链接问题的一个答案中,显示了与此类似的代码:

List<Integer> ordered = Arrays.asList(
    1, 2, 3, 4, 4, 3, 2, 1, 1, 2, 3, 4, 4, 3, 2, 1, 1, 2, 3, 4);
List<Integer> result = new CopyOnWriteArrayList<>();

ordered.parallelStream().forEach(result::add);

System.out.println(ordered);
System.out.println(result);
Run Code Online (Sandbox Code Playgroud)

这些名单确实不同.该unordered列表甚至从一次运行变为另一次运行,表明结果实际上是非确定性的.

所以我创建了另一个例子:

CopyOnWriteArrayList<Integer> result2 = ordered.parallelStream()
        .unordered()
        .collect(Collectors.toCollection(CopyOnWriteArrayList::new));

System.out.println(ordered);
System.out.println(result2);
Run Code Online (Sandbox Code Playgroud)

我希望看到类似的结果,因为流是并行和无序的(可能unordered()是多余的,因为它已经是并行的).但是,生成的列表是有序的,即它等于源列表.

所以我的问题是为什么收集的清单是有序的?是否collect总是尊重遭遇顺序,即使对于并行,无序的流?它Collectors.toCollection(...)是强制遭遇秩序的特定收集者吗?

Lou*_*man 6

Collectors.toCollection返回Collector缺少Collector.Characteristics.UNORDERED特征的a.另一个指定的收集器Collector.Characteristics.UNORDERED可能表现不同.

这就是说:"无序"意味着没有保证,不能保证变化. 如果库发现最简单的方法是按顺序处理无序集合,则允许这样做,并且允许该行为在周二或者满月时将释放更改为释放.

(另请注意,Collectors.toCollection如果您要使用并行流,则不需要使用并发集合实现; toCollection(ArrayList::new)可以正常工作.这是因为收集器没有Collector.Characteristics.CONCURRENT特性,因此它使用适用于非集合的集合策略即使使用并行流也可以并发收集.)

如果你使用无序流但是收集器不是UNORDERED,反之亦然,我怀疑你从框架得到任何保证.如果有一个表,它会说:"在这里DRAGONS未定义的行为." 我也期望在这里对不同类型的链式操作存在一些差异,例如Eugene提及findFirst在这里变化,即使findFirst本质上是有序操作 - unordered().findFirst()变得相当于findAny().

因为Stream.collect,我认为目前的实施有三种策略:

  • 顺序:启动一个累加器,将元素累积到它中(按照相遇顺序,因为你为什么要打扰工作来洗牌元素?按照你得到它们的顺序接受它们),调用整理器.
  • 并行执行,并发收集器以及流或收集器是无序的:一个累加器,分片输入,工作线程处理每个分片中的元素,并在它们准备好时将元素添加到累加器,调用整理器.
  • 并行执行,其他任何事情:将输入分片为N个分片,每个分片按顺序累积到其自己的不同累加器中,累加器与组合器功能结合,调用整理器.

  • @JBNizet完全正确.在链接的答案中,这个确切的差异使用`findFirst`提供,实际上从8变为9. (4认同)
  • 因此,在这种情况下,保留订单的事实是可以在以后更改的实现细节,对吧?toCollection提交尊重顺序,但是流是无序的,因此输出可能与源不同,对吧? (2认同)
  • @Eugene我更多地指的是方法名称中存在单词"first",使其直观地成为有序操作.我已经说过`unordered().findFirst()`相当于`findAny()`,一个无序操作.我们在同一页上,我们只是用不同的方式表达它. (2认同)