我正在阅读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();
?听起来很奇怪,至少可以说......
答案 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;上面的例子, 即使在排序约束下,仍然可以高效并行化。