.collect是否保证在并行流上排序? [英] Is .collect guaranteed to be ordered on parallel streams?

查看:198
本文介绍了.collect是否保证在并行流上排序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

鉴于我有一个字符串列表 List< String>麦克罗公司一直供应。结果必须按原始线的顺序排列。
我想利用新的并行流。

Given I have a list of Strings List<String> toProcess. The results have to be in the order the original lines were given. I want to utilize the new parallel streams.

以下代码保证结果是否与他们的顺序相同在原始列表中?

Does the following code guarantee that the results will be in the same order they were in the original list?

// ["a", "b", "c"]
List<String> toProcess;

// should be ["a", "b", "c"]
List<String> results = toProcess.parallelStream()
                                .map(s -> s)
                                .collect(Collectors.toList());


推荐答案

TL; DR



是的,订单有保证。

TL;DR

Yes, the order is guaranteed.

起点是看是什么决定了减少是否并发。 Stream.collect() 的说明如下:

The starting place is to look at what determines whether a reduction is concurrent or not. Stream.collect()'s description says the following:


如果流是并行的,并且收集器并发,流无序或收集器无序,然后执行并发减少(参见 收藏家 了解详情同时减少。)

If the stream is parallel, and the Collector is concurrent, and either the stream is unordered or the collector is unordered, then a concurrent reduction will be performed (see Collector for details on concurrent reduction.)

满足第一个条件:流是并行的。第二个和第三个怎么样:收藏家并发和无序?

 

The first condition is satisfied: the stream is parallel. How about the second and third: is the Collector concurrent and unordered?
 

toList() 的文档内容如下:

toList()'s documentation reads:


返回收集器,将输入元素累积到新的列表。返回的 List 的类型,可变性,可序列化或线程安全性无法保证;如果需要对返回的 List 进行更多控制,请使用 toCollection(Supplier)

Returns a Collector that accumulates the input elements into a new List. There are no guarantees on the type, mutability, serializability, or thread-safety of the List returned; if more control over the returned List is required, use toCollection(Supplier).

返回:

a收集器将所有输入元素收集到列表中,遇到订单

遭遇订单按原始顺序对元素进行操作。这会覆盖并行性。

 

An operation that works in encounter order operates on the elements in their original order. This overrides parallelness.
 

检查<的执行情况code> Collectors.java 确认 toList() 包含 CONCURRENT UNORDERED traits。

Inspecting the implementation of Collectors.java confirms that toList() does not include the CONCURRENT or UNORDERED traits.

public static <T>
Collector<T, ?, List<T>> toList() {
    return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
                               (left, right) -> { left.addAll(right); return left; },
                               CH_ID);
}

// ...

static final Set<Collector.Characteristics> CH_ID
        = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));

注意收藏家如何拥有 CH_ID 特征set,只有一个 IDENTITY_FINISH 特征。 CONCURRENT UNORDERED 不存在,因此减少不能并发。

Notice how the collector has the CH_ID trait set, which has only the single IDENTITY_FINISH trait. CONCURRENT and UNORDERED are not there, so the reduction cannot be concurrent.

非并发减少意味着,如果流是并行的,则可以并行进行收集,但是它将被拆分为几个线程限制的中间结果,然后进行组合。这样可确保合并结果符合订单。

 

A non-concurrent reduction means that, if the stream is parallel, collection can proceed in parallel, but it will be split into several thread-confined intermediate results which are then combined. This ensures the combined result is in encounter order.
 

另请参阅: 为什么在Java 8中按顺序收集并行流

这篇关于.collect是否保证在并行流上排序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆