使用Java 8是否正确执行以下代码当然从Collection
获取并行流?
private <E> void process(final Collection<E> collection) {
Stream<E> stream = collection.parallelStream().parallel();
//processing
}
来自Collection
API:
默认Stream parallelStream()
以此集合作为源返回可能并行的Stream。此方法允许返回顺序流。
来自BaseStream
API:
S parallel()
返回并行的等效流。可能会返回自己,因为流已经并行,或者因为基础流状态被修改为并行。
我需要调用一个可以将流并行化两次的函数,这不是很尴尬吗?
答案 0 :(得分:3)
基本上Collection.parallelStream()
的默认实现确实会创建并行流。实现如下:
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
但这是一种默认方法,对于某些实现类来说,提供不同的实现来创建顺序流也是完全有效的。例如,假设我创建了一个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()
会给你一个连续的流。