当前位置: 首页 > 知识库问答 >
问题:

如何保证java8流中处理的顺序?

山鸿彩
2023-03-14

我想在xmlJava对象中处理列表。我必须确保处理所有的元素,以便我收到他们。

因此,我是否应该对我使用的每个调用sequentialList.Stream().Sequential().Filter().Foreach()

或者,只要不使用并行性,只使用流就足够了吗?list.stream().filter().foreach()

共有2个答案

温开畅
2023-03-14

排序取决于源数据结构和中间流操作。假设您使用的是list,那么处理应该是有序的(因为filter在这里不会更改顺序)。

JavaDocs

S sequential()
Returns an equivalent stream that is sequential. May return itself, either because the stream was already sequential, or because the underlying stream state was modified to be sequential.
This is an intermediate operation.
S parallel()
Returns an equivalent stream that is parallel. May return itself, either because the stream was already parallel, or because the underlying stream state was modified to be parallel.
This is an intermediate operation.
S unordered()
Returns an equivalent stream that is unordered. May return itself, either because the stream was already unordered, or because the underlying stream state was modified to be unordered.
This is an intermediate operation.

JavaDocs

流可能具有定义的遇到顺序,也可能没有定义的遇到顺序。流是否有遇到顺序取决于源和中间操作。某些流源(如列表或数组)是内在有序的,而其他流源(如HashSet)则不是。一些中间操作(如sorted())可能会对无序的流施加偶遇顺序,而其他操作可能会使有序的流无序化,如basestream.unordered()。此外,一些终端操作可能忽略遇到顺序,例如forEach()。

如果一个流是有序的,那么大多数操作都被限制为按它们遇到的顺序对元素进行操作;如果流的源是包含[1,2,3]的列表,那么执行html" target="_blank">map(x->x*2)的结果必须是[2,4,6]。但是,如果源没有定义的遇到顺序,那么值[2,4,6]的任何排列都将是有效的结果。

对于顺序流,有无遇到顺序不影响性能,只影响确定性。如果对一个流进行排序,那么在一个相同的源上重复执行相同的流管道将产生相同的结果;如果不对其进行排序,重复执行可能会产生不同的结果。

对于并行流,放松排序约束有时可以实现更高效的执行。如果元素的排序不相关,则可以更有效地实现某些聚合操作,例如筛选重复项(distinct())或分组约简(Collectors.GroupingBy())。类似地,在本质上绑定到遇到顺序的操作(如limit())可能需要缓冲以确保正确的顺序,从而破坏了并行性的好处。在流有遇到顺序但用户并不特别关心遇到顺序的情况下,使用unordered()显式地解除流的顺序可能会提高某些状态操作或终端操作的并行性能。然而,大多数流管道,例如上面的“块权重之和”示例,即使在排序约束下仍然高效地并行化。

谷梁煌
2023-03-14

你问错了问题。您询问的是sequentialparallel之间的关系,而您希望按顺序处理项目,因此必须询问排序问题。如果您有一个有序流,并且执行了保证维持该顺序的操作,那么该流是并行处理还是顺序处理都无关紧要;执行将维持秩序。

ordered属性不同于parallel和Sequential。例如。如果对哈希集调用stream(),则在对列表调用stream()返回有序流时,流将是无序的。请注意,您可以调用unordered()来释放订购合同并潜在地提高性能。一旦流没有排序,就无法重新建立排序。(将无序流转换为有序流的唯一方法是调用sorted,但是,得到的顺序不一定是原始顺序)。

另请参阅java.util.Stream包文档的“Ordering”部分。

为了确保在整个流操作中维护订单,您必须研究流的源、所有中间操作和终端操作的文档,以确定它们是否维护订单(或者源首先是否有订单)。

这可能非常微妙,例如stream.iterate(T,UnaryOperator)创建有序流,而stream.generate(Supplier)创建无序流。请注意,您在问题中还犯了一个常见错误,因为foreach不维护顺序。如果要按照保证的顺序处理流的元素,则必须使用foreachordered

因此,如果问题中的list确实是java.util.list,那么它的stream()方法将返回一个有序流,filter不会更改顺序。因此,如果调用List.Stream().filter().ForeachOrdered(),所有元素都将按顺序被处理,而对于List.ParallelStream().filter().ForeachOrdered(),元素可能被并行处理(例如,由筛选器处理),但终端操作仍将按顺序调用(这显然会降低并行执行的好处)。

例如,如果使用以下操作

List<…> result=inputList.parallelStream().map(…).filter(…).collect(Collectors.toList());

整个操作可能会从并行执行中受益,但无论使用并行流还是顺序流,结果列表的顺序都是正确的。

 类似资料:
  • 问题内容: 我想处理对象中的列表。我必须确保处理所有元素,以便收到它们。 因此l,我应该使用它吗? 还是只要不使用并行性就足以使用流? 问题答案: 你在问错问题。你正在询问而要按顺序处理项目,因此你必须询问订购。如果你有顺序的流并执行保证维持顺序的操作,则该流是并行处理还是顺序处理都没有关系;实施将维持秩序。 有序属性不同于并行与顺序。例如,如果你调用一个同时调用流将是无序在List返回的有序流。

  • 以下代码正在为空的属性抛出NPE。class Person有属性:string:name,Integer:age,Integer:salary此处可以为空。我想创建一个工资列表。 在这里,我必须在结果列表中保留空值。null不能替换为0。

  • 我试图从流中获取订单地图。我有下一个代码: 在这里,我尝试对数据流进行排序,我认为地图也是有序的。但我错了。我认为调用collect(Collectors.toMap())不会保存流的顺序。有我如何做到这一点的例子吗?

  • 是否有任何保证在顺序和有序流上的操作是按遇到顺序处理的? 我是说,如果我有这样的代码: 是否可以保证它将按照生成范围的遇到顺序执行myFunction()调用? 我找到了Stream类的JavaDocs草案,它明确地说明了以下内容: 对于顺序流管道,如果管道源具有已定义的遇到顺序,则所有操作都按照管道源的遇到顺序执行。 但是它没有提到顺序流,这个例子是针对并行流的(我的理解是,顺序流和并行流都是正

  • 我们有1000多条数据,请求1000次第三方个接口, 效率很是低下! 所以我想利用多线程的方式快速的调用完这1000次接口请求并处理响应 但是有个问题,线程是在for循环中执行的,调用顺序肯定是错乱的,这就导致接调用后 返回的结果肯定和List中的不匹配了··· 这种情况怎么能保证顺序呢?这是我的代码

  • 我已经讨论了一些相关问题,比如如何确保java8流中的处理顺序?,我仍然不完全清楚输出元素的顺序。因此,请澄清我的以下疑问。 我认为至少在理论上(或根据java规范),它可以按1、2、3、4、5、6、7、8以外的随机顺序打印。我说得对吗? 还有一个相关的问题——遭遇订单保存的决定是在执行的哪个点做出的?更准确地说,在执行开始之前,是否通过检查源、中间操作和终端操作的特性来评估整个流水线的订单特性?