0

I want to iterate a HashMap like:

 for (Map.Entry<Integer, Integer> entry : map.entrySet()) { map.replace(entry.getKey(), entry.getValue()-1); if (entry.getValue() == 0) { map.remove(entry.getKey(), 0); } } 

This ends in an Exception: java.util.ConcurrentModificationException

Any solutions?

Kind regards

2
  • 1
    Use an iterator instead. Commented Mar 29, 2017 at 20:42
  • 4
    "If the map is modified while an iteration over the set is in progress (except through the iterator's own remove operation, or through the setValue operation on a map entry returned by the iterator) the results of the iteration are undefined." docs.oracle.com/javase/8/docs/api/java/util/Map.html#entrySet-- Here, "undefined" means to throw a CME. Commented Mar 29, 2017 at 20:52

3 Answers 3

1
 Iterator<Map.Entry<Integer, Integer>> entryItr = map.entrySet().iterator(); while (entryItr.hasNext()) { Map.Entry<Integer, Integer> entry = entryItr.next(); if (entry.getValue() > 1) { entry.setValue(entry.getValue() - 1); } else { entryItr.remove(); } } 
Sign up to request clarification or add additional context in comments.

Comments

0

You're removing items from the map as you're iterating through it. This is what's causing the exception.

To get a bit of intuition as to why this is: if your map contains three items and on the first iteration you remove the first item, should the next item be the second, or third? i.e. should the iteration continue as though the removed item was still there? And if so, how?

You can get around this by using an iterator on the map which safely goes through each element of the map.

Comments

0

You can't remove elements from an existing Set without using Iterator, otherwise, it will throw ConcurrentModificationException

So, place values to a new Map object if(value-1 !=0) as shown below:

 Map<Integer, Integer> map = new HashMap<>(); Map<Integer, Integer> newMap = new HashMap<>(); Iterator<Integer> iterator =map.keySet().iterator(); while(iterator.hasNext()) { int key = iterator.next(); int value = map.get(key); if(value-1 !=0) { newMap.put(key, value-1); } } 

3 Comments

You can do it in-place with Iterator.remove(). Why wouldn't you?
OP wants to modify the value for an existing key
Yes, and? You can use Entry.setValue for entries that aren't being removed, and Iterator.remove for entries that are.