【问题标题】:Obtaining a parallel Stream from a Collection从集合中获取并行流
【发布时间】:2014-03-22 11:15:20
【问题描述】:

使用 Java 8 是否需要执行以下代码才能肯定Collection 获取并行流?

private <E> void process(final Collection<E> collection) {
    Stream<E> stream = collection.parallelStream().parallel();
    //processing
}

来自Collection API:

默认流并行流()

返回一个可能是并行的 Stream,这个集合作为它的源。此方法允许返回顺序流。

来自BaseStream API:

S 并行()

返回一个等效的并行流。可能会返回自身,因为流已经是并行的,或者因为底层流状态被修改为并行。

我需要调用一个应该将流并行化两次的函数不是很尴尬吗?

【问题讨论】:

  • 并非所有的 collectionsstream 都支持并行执行,但所有的集合和流都有这些。我认为这就是奇怪文档的原因。所以。不。您不必调用这两种方法。
  • @nosid 但是如果这个方法被一个不支持并行的集合调用,那么parallelStream()会返回一个顺序流,但是parallel()的约定保证流会 平行。这会导致我需要调用这两种方法?

标签: java java-8 java-stream


【解决方案1】:

基本上Collection.parallelStream() 的默认实现确实创建了一个并行流。实现如下所示:

default Stream<E> parallelStream() {
    return StreamSupport.stream(spliterator(), true);
}

但这是一种默认方法,对于某些实现类来说,提供不同的实现来创建 sequential 流也是完全有效的。例如,假设我创建了一个SequentialArrayList

class MySequentialArrayList extends ArrayList<String> {
    @Override
    public Stream<String> parallelStream() {
        return StreamSupport.stream(spliterator(), false);
    }
}

对于该类的对象,以下代码将按预期打印false

ArrayList<String> arrayList = new MySequentialArrayList();
System.out.println(arrayList.parallelStream().isParallel());

在这种情况下,调用BaseStream#parallel() 方法可确保返回的流始终是并行的。通过将parallel 字段设置为true,它要么已经并行,要么使其并行:

public final S parallel() {
    sourceStage.parallel = true;
    return (S) this;
}

这是AbstractPipeline#parallel()方法的实现。

因此,相同对象的以下代码将打印true

System.out.println(arrayList.parallelStream().parallel().isParallel());

但是如果流已经是并行的,那么是的,这是一个额外的方法调用,但这将确保您始终获得并行流。我还没有深入研究流的并行化,所以我无法评论哪种集合或在什么情况下parallelStream() 会给你一个顺序流。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-16
    • 1970-01-01
    • 2017-09-09
    • 1970-01-01
    • 2011-09-07
    • 1970-01-01
    • 1970-01-01
    • 2015-03-05
    相关资源
    最近更新 更多