小编典典

是否可以确保在并行流上订购.collect?

java

鉴于我有一个字符串列表List<String> toProcess。结果必须按照原始行的顺序排列。我想利用新的并行流。

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

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

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

阅读 217

收藏
2020-09-28

共1个答案

小编典典

TL; DR

是的,订单得到保证。

Stream.collect()API文档

出发点是看什么决定减少是否同时发生。Stream.collect()的描述如下:

如果该流是并行的,并且Collector并发的,或者该流是无序的或收集器是无序的,那么将执行并发缩减(请参阅Collector有关并发缩减的详细信息。)

满足第一个条件:流是并行的。第二个和第三个如何:Collector并发和无序?

Collectors.toList()API文档

toList()的文档内容如下:

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

返回:
一个收集器, 以遇到的顺序 将所有输入元素收集到一个List

相遇顺序工作的操作按其原始顺序对元素进行操作。这将覆盖并行性。

实施代码

检查实施Collectors.java确认toList()没有 包含CONCURRENTUNORDERED特征。

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特征集,该特征集仅具有单个IDENTITY_FINISH特征。CONCURRENT并且UNORDERED不存在,因此减少不能并发。

非并行减少意味着,如果流是并行的,则收集可以并行进行,但是它将被拆分为多个线程限制的中间结果,然后将其合并。这样可以确保组合结果按相遇顺序排列。

2020-09-28