Reputation: 313
I have an executer service with a thread pool of 3 and each thread is accessing a synchronizedList and converting it to a list of Map
List<String> fruitList = Collections.synchronizedList(new ArrayList<>());
fruitList.add("banana");
fruitList.add("banana");
fruitList.add("banana");
fruitList.add("banana");
fruitList.add("kiwi");
fruitList.add("mango");
fruitList.add("mango");
fruitList.add("papaya");
I want to convert this list to a list of map where fruitName will be key and frequency of item will be the value
[{"banana" : 4}, {"mango" : 2}, {"kiwi" : 1}, {"papaya" :1}]
I tried something like this
Map<String, Long> fruitMap = fruitList.stream().collect(Collectors.
groupingBy(e -> e, Collectors.counting()));
But, occasionally I am getting the following error. How can I resolve this?
[java] Exception in thread "pool-3-thread-3" java.util.ConcurrentModificationException
[java] at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1388)
[java] at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
[java] at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
[java] at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
[java] at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
[java] at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:566)
Upvotes: 0
Views: 537
Reputation: 894
If fruitList
is updated in the middle of .stream().collect()
process, you shall get that exception. A proper critical section definition and synchronization should be created to avoid that.
Although Collections.synchronizedList()
does synchronization for most of the methods, it does not synchronize Collection.stream()
and other methods on the stream. You need to synchronize your stream process manually.
That should work:
synchronized(fruitList) {
Map<String, Long> fruitMap = fruitList.stream()
.collect(Collectors.groupingBy(e -> e, Collectors.counting()));
}
Upvotes: 1