Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 995
quma Avatar asked Dec 06 '22 17:12

quma


1 Answers

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());
like image 99
JB Nizet Avatar answered Jun 07 '23 14:06

JB Nizet