有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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());

共 (2) 个答案

  1. # 1 楼答案

    TL;DR

    是的,订单是有保证的

    小溪。collect()API文档

    首先要看看是什么决定了减量是否同时进行^{}的描述如下:

    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.)

    满足第一个条件:流是平行的。第二个和第三个呢:Collector是并发的、无序的吗

    收藏家。toList()API文档

    ^{}的文件内容如下:

    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).

    Returns:
    a Collector which collects all the input elements into a List, in encounter order

    encounter order中工作的操作按元素的原始顺序对其进行操作。这压倒了平行性

    实现代码

    检查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特征CONCURRENTUNORDERED不存在,因此还原不能同时进行

    非并发缩减意味着,如果流是并行的,则收集可以并行进行,但它将被拆分为多个线程限制的中间结果,然后将这些结果合并。这确保了组合结果的顺序

    另请参见:Why parallel stream get collected sequentially in Java 8

  2. # 2 楼答案

    你一定会把元素按顺序排列好

    documentation of ^{}

    Returns: a Collector which collects all the input elements into a List, in encounter order

    参见java.util.streams summary了解关于“遭遇顺序”一词的更多信息

    此外,^{}文档要求List的所有实现生成ORDERED的拆分器:

    The Spliterator reports Spliterator.SIZED and Spliterator.ORDERED. Implementations should document the reporting of additional characteristic values.

    奇怪的是,虽然List接口需要iterator()以“正确的顺序”生成元素,但是spliterator()只需要按顺序排列,而不需要按照列表的自然顺序排列

    因此,为了回答您的问题,toList生成的列表保证包含的元素与源列表的拆分器对元素的排序完全相同。流是并行的还是顺序的并不重要