Reputation: 325
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
Reputation: 308
According to Oracles documentation
Like reduce(int, IntBinaryOperator), collect operations can be parallelized without requiring additional synchronization.
So it seems like your intuition is right that this is thread-safe.
Upvotes: 4
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