关于Characteristics.UNORDERED在Java 8中的行动书中的混淆

Cod*_*Man 4 java java-8 java-stream

java 8的作者在写这个类:

class ToListCollector<T> implements Collector<T, List<T>, List<T>> {

    @Override
    public Supplier<List<T>> supplier() {
        return ArrayList::new;
    }

    @Override
    public BiConsumer<List<T>, T> accumulator() {
        return List::add;
    }

    @Override
    public BinaryOperator<List<T>> combiner() {
        return (l1, l2) -> {
            l1.addAll(l2);
            return l1;
        };
    }

    @Override
    public Function<List<T>, List<T>> finisher() {
        return Function.identity();
    }

    @Override
    public Set<Characteristics> characteristics() {
        return Collections.unmodifiableSet(EnumSet.of(Characteristics.IDENTITY_FINISH, Characteristics.CONCURRENT));
    }
}
Run Code Online (Sandbox Code Playgroud)

然后他谈到了特征枚举中的不同值.然后他解释了为什么他写的这个收藏家是IDENTITY_FINISH和CONCURRENT而不是UNORDERED,他说:

到目前为止开发的ToListCollector是IDENTITY_FINISH,因为用于累积流中元素的List已经是预期的最终结果,不需要任何进一步的转换,但它不是UNORDERED,因为如果你将它应用于有序流你希望在生成的List中保留此顺序.最后,它是CONCURRENT,但是按照我们刚才所说的,只有当它的底层数据源是无序的时,才会并行处理流.

为什么只有当底层源无序时才会并行处理流?我认为它仍然会并行处理,但是combiner()必须保留顺序.这本书中的错误是什么?

我认为Brian Goetz 在最后一篇文章中非常明确地谈到了这篇文章中有序流的并行处理.

书中的页面是192 - 193.

Eug*_*ene 7

这完全是错的.即使CONCURRENT在这里添加特性也是错误的,因为你需要一个线程安全的数据结构Supplier.

  • 请注意,即使没有*无序*收集器特性,这也可能在实践中中断.或者,当流是无序的,或者当你将它用作`groupingByConcurrent`的下游收集器时.在这些情况下,流将尝试利用此收集器的声明的*concurrent*性质. (2认同)