是否有一个操作的任何保证连续和有序流的处理,在遭遇订单?
我的意思是,如果我有这样的代码:
IntStream.range(0, 5)
.map(i -> {
myFunction(i);
return i * 2;
})
.boxed()
.collect(toList());
Run Code Online (Sandbox Code Playgroud)
是否有保证,它将以生成范围的遭遇顺序执行myFunction()调用?
我找到了Stream类的JavaDocs草案,明确说明了这一点:
对于顺序流管道,如果管道源具有已定义的遭遇顺序,则所有操作都以管道源的遭遇顺序执行.
但在官方JavaDocs中,这一行被删除了.它现在仅讨论所选方法的遭遇顺序.该包装java.util.stream文档的副作用款规定:
即使管道被约束以产生与流源的遭遇顺序一致的结果(例如,
IntStream.range(0,5).parallel().map(x -> x*2).toArray()必须产生[0, 2, 4, 6, 8]),也不保证将映射器函数应用于各个元素的顺序,或者什么线程为给定元素执行任何行为参数.
但它没有说明顺序流,而且这个例子是针对并行流的(我的理解是顺序流和并行流都是如此,但这是我不确定的部分).
另一方面,它也在订购部分说明:
如果订购了流,则大多数操作都被约束为对其遭遇顺序中的元素进行操作; 如果流的源是
List包含的[1, 2, 3],那么执行的结果map(x -> x*2)必须是[2, 4, 6].但是,如果源没有定义的遭遇顺序,则值的任何排列[2, 4, 6]都将是有效结果.
但这一次它以"对元素进行操作"开始,但是示例是关于产生的流,所以我不确定它们是否会考虑副作用,副作用实际上就是这个问题.
我认为我们可以从这个明确的句子被删除的事实中学到很多东西。这个问题似乎与问题\xe2\x80\x9cDoes Stream.forEach 尊重顺序流的遇到顺序吗?\xe2\x80\x9d密切相关。Brian Goetz 的答案基本上是说,尽管事实上在forEach顺序 Stream 上调用时,\xe2\x80\x99s 不存在 Stream\xe2\x80\x99s 当前实现忽略顺序的情况,但forEach 可以自由地忽略即使对于每个规范的顺序流,遇到顺序也是如此。
Stream现在考虑\xe2\x80\x99s 类文档的以下部分:
\n\n\n为了执行计算,流操作被组合成流管道。流管道由源(可能是数组、集合、生成器函数、I/O 通道等)、零个或多个中间操作(将一个流转换为另一个流,例如
\nfilter(Predicate))和一个终端操作(产生结果或副作用,例如count()或forEach(Consumer))。流是惰性的;仅在启动终端操作时才执行对源数据的计算,并且仅在需要时消耗源元素。
由于是终端操作决定是否需要元素以及是否需要按遇到顺序排列元素,因此终端操作\xe2\x80\x99 忽略遇到顺序的自由也意味着以任意顺序消耗并处理元素。
\n\n注意,不仅forEach可以做到这一点。ACollector具有报告特征的能力UNORDERED,例如Collectors.toSet()不依赖于遭遇顺序。很明显,像 Java\xc2\xa09 中的 \xe2\x80\x99t 这样的操作并不count()依赖于顺序 \xe2\x80\x94,它甚至可能在没有任何元素处理的情况下返回。想IntStream#sum()另一个例子。
在过去,实现过于急切地在流中传播无序特征,请参阅\xe2\x80\x9c 这是 Files.lines() 中的错误,还是我误解了有关并行流的内容?\xe2\x80\x9d其中终端操作影响了步骤的结果,这就是当前实现skip不愿意进行此类优化以避免类似错误的原因,但这并不排除此类优化的重新出现,然后用更多的方法来实现关心\xe2\x80\xa6
因此,目前\xe2\x80\x99很难想象实现如何通过利用顺序流中无序评估的自由度来获得性能优势,但是,正如相关问题中所述forEach,这并不\xe2\ x80\x99t 暗示任何保证。
| 归档时间: |
|
| 查看次数: |
1088 次 |
| 最近记录: |