Java-8 parallelStream(...) - >填充ArrayList

时间:2016-08-23 05:43:13

标签: java-8 java-stream

我试过这段代码:

 final List<ScheduleContainer> scheduleContainers = new ArrayList<>();
 scheduleResponseContent.getSchedules().parallelStream().forEach(s -> scheduleContainers.addAll(s));

使用parallelStream,我得到一个ArrayIndexOutOfBoundException或NullpointerException,因为 scheduleContainers 中的某些条目为空。

使用... .stream()......一切正常。 我现在的问题是,是否有可能解决这个问题或者我是否误用了parallelStream?

2 个答案:

答案 0 :(得分:7)

是的,你误用了parallelStream。首先,as you have already said twice in your previous question,默认情况下应使用stream(),而不是parallelStream()。并行具有内在成本,通常会使事情的效率低于简单的顺序流,除非您有一个大量数据要处理,并且每个元素的过程需要时间。您应该遇到性能问题,并在使用之前测量并行流是否解决了该问题。正如你的帖子所示,还有更大的机会搞乱并行流。

阅读Should I always use a parallel stream when possible?以获取更多参数。

其次,这段代码根本不是线程安全的,因为它使用几个并发线程来添加到线程不安全的ArrayList。如果您使用collect()为您创建最终列表而不是forEach()并且自己将内容添加到列表中,则可以是安全的。

代码应为

List<ScheduleContainer> scheduleContainers =
    scheduleResponseContent.getSchedules().
                           .stream()
                           .flatMap(s -> s.stream())
                           .collect(Collectors.toList());

答案 1 :(得分:4)

不确定错误的原因,但有更好的方法可以使用Stream API从多个输入列表创建List。

final List<ScheduleContainer> scheduleContainers =
    scheduleResponseContent.getSchedules()
                           .parallelStream()
                           .flatMap(s->s.stream()) // assuming getSchedules() returns some 
                                                   // Collection<ScheduleContainer>, based 
                                                   // on your use of addAll(s)
                           .collect(Collectors.toList());