quma
quma

Reputation: 5719

Java-8 parallelStream(...) -> fill ArrayList

I have tried this code:

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

With parallelStream I get either an ArrayIndexOutOfBoundException or a NullpointerException because some entries in scheduleContainers are null.

With ... .stream()... everything works fine. My question now would be if there is a possibiliy to fix this or did I misuse parallelStream?

Upvotes: 5

Views: 15406

Answers (2)

JB Nizet
JB Nizet

Reputation: 691933

Yes, you are misusing parallelStream. First of all, as you have already said twice in your previous question, you should use stream(), and not parallelStream(), by default. Going parallel has an intrinsic cost, that usually makes things less efficient than a simple sequential stream, unless you has a massive amount of data to process, and the process of each element takes time. You should have a performance problem, and measure if a parallel stream solves it, before using one. There's also a much bigger chance of screwing up with a parallel stream, as your post shows.

Read Should I always use a parallel stream when possible? for more arguments.

Second, this code is not thread-safe at all, since it uses several concurrent threads to add to a thread-unsafe ArrayList. It can be safe if you use collect() to create the final list for you instead of forEach() and add things to the list by yourself.

The code should be

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

Upvotes: 10

Eran
Eran

Reputation: 393936

Not sure about the cause of the error, but there are better ways to use the Stream API to create a List from multiple input Lists.

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());

Upvotes: 6

Related Questions