假设我们有一个标准的流操作方法链:
Arrays.asList("a", "bc", "def").stream()
.filter(e -> e.length() != 2)
.map(e -> e.length())
.forEach(e -> System.out.println(e));
JLS 中是否对流操作应用于列表元素的顺序有任何保证?
例如,是否保证:
- 将过滤谓词应用于
"bc"
在应用过滤谓词之前不会发生"a"
?
- 将映射函数应用到
"def"
在应用映射函数之前不会发生"a"
?
-
1
将在之前打印3
?
Note: 我这里专门讲一下stream()
, not parallelStream()
预计映射和过滤等操作是并行完成的。
你想知道的一切都可以在java.util.stream JavaDoc.
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(使用前将#替换为@)