据我所知,并行流中,诸如findFirst
,skip
,limit
之类的方法只要保持其行为只要无论是否并行,流都是有序的(默认情况下)。所以我想知道为什么forEach
方法是不同的。我考虑了一下,但我只是不明白定义forEachOrdered
方法的必要性,因为将forEach
缺省设置为序,然后调用{{1}在流实例上就是这样,无需定义新方法。
不幸的是,在这一点上,我在Java 8方面的实践经验非常有限,因此,如果有人可以向我解释此架构决定的原因,也许我会通过一些简单的示例/用例向我展示否则可能会出错,我将不胜感激
为了明确起见,我不是在问这个问题:forEach vs forEachOrdered in Java 8 Stream。我完全知道这些方法如何工作以及它们之间的差异。我要问的是Oracle做出体系结构决策的实际原因。
答案 0 :(得分:3)
当您并行处理Stream的元素时,您应该不要期望在订单上有任何保证。
整个想法是,多个线程在该流的不同元素上工作。它们分别进行,因此处理顺序不可可预测。它是不确定的,又称随机。
我可以想象有意实现该接口的人 会给您随机的顺序,从而使您真正清楚不会有任何期望使用并行流时,顺序不同。
答案 1 :(得分:3)
诸如findFirst
,limit
和skip
之类的方法需要输入顺序,因此无论我们使用并行流还是串行流,它们的行为都不会改变。但是,forEach
作为一种方法不需要任何顺序,因此其行为是不同的。
对于并行流管道,forEach
操作不能保证尊重流的遇到顺序,因为这样做会牺牲并行性的好处。
我还建议不要将findFirst
,limit
和skip
与并行流一起使用,因为由于订购并行流所需的开销,这会降低性能。
答案 2 :(得分:3)
定义方法forEach
可以保留顺序,而unordered
可以破坏顺序,这会使IMO复杂化;仅仅因为unordered
只是在流api内部设置标记而已,而标记检查则必须根据某些条件来执行或强制执行。
因此,假设您会这样做:
someStream()
.unordered()
.forEach(System.out::println)
在这种情况下,您的建议是不要以任何顺序打印元素,因此在此处强制 unordered
。但是,如果我们这样做了:
someSet().stream()
.unordered()
.forEach(System.out::println)
在这种情况下,您想强制执行unordered
吗?毕竟,流的源是Set
,它没有顺序,因此,在这种情况下,强制执行unordered
只是没有用。但这意味着要在内部对流的源进行其他测试。这可能会变得非常棘手和复杂(因为它已经是btw)了。
为简化起见,定义了两种方法,明确规定了它们的作用。例如findFirst
与findAny
甚至 Optional::isPresent
和Optional::isEmpty
(在Java-11中添加)。 >