我正在阅读 Richard Warburton 所著的 Java 8 书籍,并得出以下结论:
某些操作在有序流上的成本更高。这个问题可以
可以通过消除排序来解决。为此,请调用流的unordered
方法。 [...]
我对此感到非常困惑。假设我们有Stream<Integer> stream = Arrays.asList(1, 2, 3, 4).stream();
Since List<Integer>
定义流的遭遇顺序 (some) 操作可能执行效率低下。这是为什么?
它如何影响处理以及导致处理速度变慢的原因是什么?为了让事情变得更快,在这种情况下,我们是否应该将其称为
Stream<Integer> stream = Arrays.asList(1, 2, 3, 4).stream().unordered();
?至少可以说,听起来很奇怪......
文档中对此进行了详细解释:https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html
Ordering
流可能有也可能没有定义的遭遇顺序。无论是否
流的遇到顺序取决于源和
中间操作。某些流源(例如 List 或
数组)本质上是有序的,而其他(例如 HashSet)
不是。一些中间操作,例如sorted(),可能会强加一个
在原本无序的流上遇到顺序,其他人可能会
将有序流渲染为无序,例如 BaseStream.unordered()。
此外,一些终端操作可能会忽略遇到的顺序,例如
forEach()。
如果流是有序的,则大多数操作都被限制为在
元素的遭遇顺序;如果流的源是
包含[1,2,3]的列表,则执行map(x -> x*2)的结果
必须是 [2, 4, 6]。但是,如果源没有定义遭遇
顺序,那么值 [2, 4, 6] 的任何排列都是有效的
结果。
对于顺序流,存在或不存在遭遇顺序
不影响性能,只影响确定性。如果一个流是有序的,
在相同的流管道上重复执行相同的流管道
源将产生相同的结果;如果没有订购,
重复执行可能会产生不同的结果。
对于并行流,放宽排序约束有时可以
实现更高效的执行。某些聚合操作,例如
过滤重复项(distinct())或分组缩减
(Collectors.groupingBy()) 可以更有效地实现,如果
元素的顺序不相关。类似地,操作是
本质上与遇到顺序相关,例如 limit(),可能需要
缓冲以确保正确排序,破坏了好处
并行性。如果流有遇到顺序,但
用户并不特别关心遇到的顺序,明确地
使用 unordered() 对流进行解序可以提高并行性
某些有状态或终端操作的性能。然而,大多数
流管道,例如上面的“块的权重总和”示例,
即使在排序限制下仍然可以有效地并行化。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)