wouterio
wouterio

Reputation: 325

Is this IntStream partioning implementation really not thread safe?

This answer provides an implementation for partioning an IntStream:

IntStream intStream = IntStream.iterate(0, i -> i + 1).limit(1000000);

Predicate<Integer> p = x -> r.nextBoolean();
Map<Boolean, List<Integer>> groups = intStream.collect(() -> {
    Map<Boolean, List<Integer>> map = new HashMap<>();
    map.put(false, new ArrayList<>());
    map.put(true, new ArrayList<>());
    return map;
}, (map, x) -> {
    boolean partition = p.test(x);
    List<Integer> list = map.get(partition);
    list.add(x);
}, (map1, map2) -> {
    map1.get(false).addAll(map2.get(false));
    map1.get(true).addAll(map2.get(true));
});

System.out.println(groups.get(false).size());
System.out.println(groups.get(true).size());

But its edit mentions that this implementation is not thread safe. As far as I can see however, the collector creates a separate HashMap<List<Integer>> for each thread in a parallel stream. So each map is confined to a single thread. The partitioning function is confined to a single thread as well. The merging function merges the results from several threads, but as far as I know the stream framework makes sure merging is done in a thread safe manner. So my question: is this solution really not thread safe?

BTW: The answer provides a more elegant solution anyway (Stream<Integer> stream = intStream.boxed(); etc), but I still like to know.

PS: I would have like to add this question as a comment to the original post, but I don't even have the reputation to add comments... :|

Upvotes: 4

Views: 384

Answers (2)

Wiingreen
Wiingreen

Reputation: 308

According to Oracles documentation

Like reduce(int, IntBinaryOperator), collect operations can be parallelized without requiring additional synchronization.

https://docs.oracle.com/javase/8/docs/api/java/util/stream/IntStream.html#collect-java.util.function.Supplier-java.util.function.ObjIntConsumer-java.util.function.BiConsumer-

So it seems like your intuition is right that this is thread-safe.

Upvotes: 4

ewramner
ewramner

Reputation: 6233

Well, Random is thread safe but should not be used in this way as it has poor performance under contention, but ArrayList is not thread safe. With a parallel stream you will call list.add(x) from multiple threads.

Upvotes: 0

Related Questions