在处理Java项目时,我遇到了如下代码:
someMap.keySet().stream().sorted().forEach(/* ... */);这里的意图显然是要为地图中的每个键做一些事情,根据键的自然顺序,这似乎是在实践中发生的事情。但是,我不确定这种行为是否得到了保证。Stream#forEach的Javadoc说:
此操作的行为是显式不确定的。对于并行流管道,此操作并不保证尊重流的遭遇顺序,因为这样做将牺牲并行性的好处。对于任何给定的元素,操作可以在库选择的任何时间和线程中执行。
我知道,如果代码使用的是.parallelStream()而不是.stream(),那么它就不能保证工作正常,但是由于它使用的是顺序流( Javadoc没有提到这一点),我不确定。这是否保证始终正常工作,或者该代码是否需要使用.forEachOrdered()而不是.forEach()呢?
编辑:我认为这个问题并不是Java 8流中的forEach与forEachOrdered的重复,因为这个问题是在问“forEach和forEachOrdered之间的区别的一个例子是什么”,而公认的答案基本上是“并行流”。这个问题是关于顺序流的。
发布于 2017-12-31 20:38:53
不能保证forEach终端操作将按相遇顺序处理元素,因此“显式不确定”。尽管在当前实现下,它应该按照流的遭遇顺序处理顺序流的元素。
forEachOrdered主要用于使用并行流并希望尊重流的遇到顺序(如果流具有定义的遭遇顺序)的情况。
在顺序流上使用forEach或forEachOrdered会产生同样的效果,所以这是一个优先考虑的问题。
如前所述,在当前的实现中,我们知道forEach终端操作应该按照流的遭遇顺序处理顺序流的元素,但是由于它没有在java中声明,所以如果您真的关心迭代顺序,最好坐在围栏上使用forEachOrdered。
发布于 2017-12-31 21:17:57
在当前的实现下,它是--但是文档非常清楚,不把它作为规则来指定。这种情况显然是可以改变的,但目前它并没有改变,即使是在这样做的时候:
Stream.of(5, 4, 3, 1)
.unordered()
.forEach(System.out::println);即使您是有意打破订单,对于顺序流,数据并不是有意在内部--至少目前没有。
但是,您必须小心,不要依赖它,因为不同版本之间可能会发生变化,这里有一个例子
发布于 2018-01-01 04:15:06
这是否保证始终工作,或者该代码是否需要使用.forEachOrdered()而不是.forEach()才能正常工作?
不是的。它不一定总是能起作用。正如javadoc所说,forEach()方法可能不是确定性的。这意味着实现者有权更改当前确定性行为不同的情况。
如果您希望确保确定性,请使用javadoc显式保证的方法。在未来的版本中,不太可能故意破坏.forEachOrdered()中对订单保存的明确保证。
所以..。我要向应用程序的维护人员指出这个错误。我们不能预测它将来会破裂,但它当然可以。潜在的虫子就是虫子。
https://stackoverflow.com/questions/48045510
复制相似问题