I have class containing multiple HashMaps. The values in these HashMaps are the same but the keys are different. I have to remove the same element from all Maps that contain it. The method that removes these elements takes a Collection
as argument, iterates over it and removes elements from multiple HashMaps.
Here is the code:
private Map<Position, Place> map1 = new HashMap<Position, Place>();
private Map<String, List<Place>> map2 = new HashMap<String, List<Place>>();
private Map<Category, List<Place>> map3 = new HashMap<Category, List<Place>>();
public void removePlaces2(Collection<Place> places) {
Iterator<Place> iter = places.iterator();
while (iter.hasNext()) {
Place p = iter.next();
Position pos = p.getPosition();
String name = p.getName();
Category cat = p.getCategory();
map1.remove(pos);
List<Place> list1 = map2.get(name);
list1.remove(p);
if (list1.isEmpty()) {
map2.remove(name);
}
if (cat != null) {
List<Place> list2 = map3.get(cat);
list2.remove(p);
}
this.remove(p);
modified = true;
}
revalidate();
}
The method throws an ConcurrentModificationException
at the line Place p = iter.next();
. (But not every time.) I'm at a loss as to how to avoid it. If I use iter.remove(p)
that will only remove the element from the argument to the method: Collection<Place> places
. And this is not what I want.
The question is how can I avoid this exception while removing the element from multiple maps?
Notice: I am not iterating over the maps from which the element is to be removed.
If you are passing map1, map2, or map3 as an argument to removePlaces2()
, create a copy instead:
removePlaces2(new LinkedList<Place>(map1.values()));
If the exception persists try using thread safe versions of the maps:
private Map<Position, Place> map1 = Collections.synchronizedMap(new HashMap<Position, Place>());
private Map<String, List<Place>> map2 = Collections.synchronizedMap(new HashMap<String, List<Place>>());
private Map<Category, List<Place>> map3 = Collections.synchronizedMap(new HashMap<Category, List<Place>>());