1

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.

11
  • What are you passing it as an argument? Commented Aug 11, 2015 at 22:12
  • What does the method this.remove(p) do? Commented Aug 11, 2015 at 22:15
  • 2
    My guess is that this.remove(p)actually removes the place from the Collection<Place> on which you're iterating, or that this collection is one of the lists stored in map2 or map3 Commented Aug 11, 2015 at 22:16
  • 2
    maybe Collection<Place> places is one of the List<Place> in map2 or map3 Commented Aug 11, 2015 at 22:17
  • 2
    you can make a copy of places, and iterate on the copy. Commented Aug 11, 2015 at 22:40

1 Answer 1

1

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>>());
Sign up to request clarification or add additional context in comments.

1 Comment

Passing on a copy of the list as the argument seems to work. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.