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

时间:2016-05-14 10:43:47

标签: java java-stream

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

  

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

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

由于List<Integer>定义了流的遇到顺序( some ),因此可能无效地执行操作。这是为什么?

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

Stream<Integer> stream = Arrays.asList(1, 2, 3, 4).stream().unordered();

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

1 个答案:

答案 0 :(得分:6)

文档中对此进行了详细说明: https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html

  

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

     

如果订购了流,则大多数操作都被限制为可以进行操作   他们遭遇顺序中的元素;如果流的来源是   列表包含[1,2,3],然后执行map的结果(x - &gt; x * 2)   必须是[2,4,6]。但是,如果源没有定义的遭遇   顺序,那么值[2,4,6]的任何排列都是有效的   结果。   对于顺序流,是否存在遭遇订单   不影响表现,只影响决定论。如果订购了流,   在相同的流程上重复执行相同的流管道   源将产生相同的结果;如果没有订购,   重复执行可能会产生不同的结果。

     

对于并行流,有时可以放宽排序约束   实现更高效的执行。某些聚合操作,例如   过滤重复(distinct())或分组缩减   (Collectors.groupingBy())可以更有效地实现   元素的排序是不相关的。同样,操作也是如此   本质上与遇到订单相关联,例如limit(),可能需要   缓冲以确保正确的订购,从而破坏了利益   并行性。 如果流有遭遇订单,但是   用户并不特别关心那次遭遇订单   使用无序()对流进行排序可以改善并行性   某些有状态或终端操作的性能。但是,大多数情况   流管道,例如块的权重总和&#34;上面的例子,   即使在排序约束下,仍然可以高效并行化。