I don't understand why I get a ConcurrentModificationException when I iterate through this multimap
.
I read the following entry, but I am not sure if I understood the whole thing.
I tried to add a synchronized block. But my doubt is what to synchronize with, and when.
The multimap
is a field and created like this :
private Multimap<GenericEvent, Command> eventMultiMap =
Multimaps.synchronizedMultimap(HashMultimap.<GenericEvent, Command> create());
and used like this :
eventMultiMap.put(event, command);
and like this ( I tried to synchronize this part on the map, but without success )
for (Entry<GenericEvent, Command> entry : eventMultiMap.entries()) {
if (entry.getValue().equals(command)) {
eventMultiMap.remove(entry.getKey(), entry.getValue());
nbRemoved++;
}
}
You may wish to see this blogpost for another pitfall yielding a ConcurrentModificationException
when traversing a multimap, with no other thread interfering. In short, if you traverse multimap's keys, accessing the respective collection of values associated with each key and remove some element from such a collection, if that element happens to be the last of the collection you are going to have ConcurrentModificationException
when you try to access the next key - because emptying a collection triggers the removal of the key, thus structurally modifying the multimap's keyset.
Calling remove on a collection while you're iterating through it will cause a ConcurrentModificationException every time, even if it's all done in the same thread - the Right Thing to do is get an explicit iterator and call .remove() on that.
Edit: Modifying your example:
Iterator<Map.Entry<GenericEvent, Command>> i = eventMultiMap.entries().iterator();
while (i.hasNext()) {
if (i.next().getValue().equals(command)) {
i.remove();
nbRemoved++;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With