在java 8中从并行流中收集

时间:2017-05-20 08:07:42

标签: java java-8 java-stream java.util.concurrent

我想获取输入并在其上应用并行流,然后我想输出为列表。输入可以是我们可以应用流的任何列表或任何集合。

我担心的是,如果我们想要输出作为映射它们,我们有一个来自java的选项就像

list.parallelStream().collect(Collectors.toConcurrentMap(args))

但是我没有选择以线程安全的方式从并行流中收集以提供列表作为输出。 我看到还有一个选项可以使用

list.parallelStream().collect(Collectors.toCollection(<Concurrent Implementation>))

通过这种方式,我们可以在collect方法中提供各种并发实现。但我认为java.util.concurrent中只存在CopyOnWriteArrayList List实现。我们可以在这里使用各种队列实现,但那些不会像列表一样。我的意思是我们可以解决这个问题。

如果我想将输出列为清单,请指导我最好的方法是什么?

注意:我找不到与此相关的任何其他帖子,任何参考都会有所帮助。

2 个答案:

答案 0 :(得分:21)

用于接收正在收集的数据的Collection对象不需要是并发的。你可以给它一个简单的ArrayList

这是因为并行流中的值集合实际上并未收集到单个Collection对象中。每个线程都将收集自己的数据,然后所有子结果将合并成一个最终的Collection对象。

Collector javadoc中记录了这一切,Collector是您collect()方法的参数:

<R,A> R collect(Collector<? super T,A,R> collector)

答案 1 :(得分:6)

But there is no option that I can see to collect from parallel stream in thread safe way to provide list as output。这是完全错误的。

流中的重点是,您可以使用非线程安全的集合来实现完全有效的线程安全结果。这是因为流的实现方式(这是流设计的关键部分)。您可以看到Collector定义了一个方法supplier,每个步骤都会创建一个新实例。这些实例将在它们之间合并。

所以这是完全线程安全的:

 Stream.of(1,2,3,4).parallel()
          .collect(Collectors.toList());

由于此流中有4个元素,因此将创建4个ArrayList实例,这些实例将在最后合并为单个结果(假设至少有4个CPU核心)

另一方面,像toConcurrent这样的方法生成单个结果容器,所有线程都会将结果放入其中。