为什么无序流比有序流更快?

use*_*882 5 java java-stream

我正在阅读Richard Warburton撰写的Java 8书,并想出了这个:

某些操作在有序流上更昂贵.这个问题可以通过消除排序来解决.为此,请调用流的 unordered方法.[...]

我对此非常困惑.假设我们有Stream<Integer> stream = Arrays.asList(1, 2, 3, 4).stream();

由于List<Integer>定义了流(某些)操作的遭遇顺序可能无效率地执行.这是为什么?

它如何影响处理以及什么使它变慢?为了使事情更快,在这种情况下,我们应该将其称为

Stream<Integer> stream = Arrays.asList(1, 2, 3, 4).stream().unordered();
Run Code Online (Sandbox Code Playgroud)

?听起来很奇怪,至少可以说......

kro*_*lko 7

这在文档中有详细解释:https: //docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html

订购
流可能有也可能没有已定义的遭遇顺序.流是否具有遭遇顺序取决于源和中间操作.某些流源(例如List或数组)本质上是有序的,而其他流(例如HashSet)则不是.某些中间操作(例如sorted())可能会在其他无序流上强制执行遭遇顺序,而其他中间操作可能会呈现无序的有序流,例如BaseStream.unordered().此外,一些终端操作可以忽略遭遇顺序,例如forEach().

如果订购了流,则大多数操作都被约束为对其遭遇顺序中的元素进行操作; 如果流的源是包含[1,2,3]的List,那么执行map(x - > x*2)的结果必须是[2,4,6].但是,如果源没有定义的遭遇顺序,那么值[2,4,6]的任何排列都将是有效的结果.对于顺序流,遭遇顺序的存在与否不会影响性能,只影响确定性.如果订购了流,则在相同的源上重复执行相同的流管道将产生相同的结果; 如果没有订购,重复执行可能会产生不同的结果.

对于并行流,放宽排序约束有时可以实现更高效的执行.如果元素的排序不相关,则可以更有效地实现某些聚合操作,例如过滤重复(distinct())或分组缩减(Collectors.groupingBy()).类似地,与遇到订单本质上相关的操作(例如limit())可能需要缓冲以确保正确排序,从而破坏并行性的好处.在流具有遭遇顺序但用户不特别关心该遭遇顺序的情况下,使用无序()明确地对流进行排序可以改善某些有状态或终端操作的并行性能.然而,大多数流管道,例如上面的"块的权重总和"示例,即使在排序约束下仍然有效地并行化.