2

I'm writing this program in Java and I'm getting a java.util.ConcurrentModificationException. The code excerpt is given below, please let me know if more code is required.

for (String eachChar : charsDict.keySet()) {
    if (charsDict.get(eachChar) < 2) {
        charsDict.remove(eachChar);
    }
}

charsDict is defined as

Map<String, Integer> charsDict = new HashMap<String, Integer>();

Please help me :)

pratnala
  • 3,723
  • 7
  • 35
  • 58

3 Answers3

6

You're not allowed to remove elements from the map while using its iterator.

A typical solution to overcome this:

List<String> toBeDeleted = new ArrayList<String>();
for (String eachChar : charsDict.keySet()) {
    if (charsDict.get(eachChar) < 2) {
        toBeDeleted.add(eachChar);
    }
}

for (String eachChar : toBeDeleted) {
    charsDict.remove(eachChar);
}
Vincent van der Weele
  • 12,927
  • 1
  • 33
  • 61
5

You need to use the remove method of the iterator:

for (Iterator<String> it = charsDict.keySet().iterator(); it.hasNext();) {
    String eachChar = it.next();
    if (charsDict.get(eachChar) < 2) {
        it.remove();
    }
}

Also note that since you need to access the key AND the value, it would be more efficient to use entrySet instead:

for (Iterator<Map.Entry<String, Integer>> it = charsDict.entrySet().iterator(); it.hasNext();) {
    Map.Entry<String, Integer> e = it.next();
    String eachChar = e.getKey();
    int value = e.getValue();
    if (value < 2) {
        it.remove();
    }
}

And finally it appears that the key is actually not used, so the loop becomes:

for (Iterator<Integer> it = charsDict.values().iterator(); it.hasNext();) {
    if (it.next() < 2) {
        it.remove();
    }
}

See also this related post.

Community
  • 1
  • 1
assylias
  • 321,522
  • 82
  • 660
  • 783
  • 1
    Accepted this as code is more concise. Thanks :) Also, I learnt what iterators are in the process. However, I must add that the code by Heuster also works perfectly. – pratnala Mar 22 '13 at 11:39
  • @pratnala Yes the other answer works too - but with the iterator you avoid creating an unnecessary list and querying the map twice (get + remove). – assylias Mar 22 '13 at 11:40
  • Woah! Just iterate on the values and remove the value. But isn't value associated with the key? So how is it different? Apart from the fact that the code is cleaner that is. – pratnala Mar 22 '13 at 11:47
  • @pratnala in the third example, `it.remove()` will effectively remove the value and the associated key. – assylias Mar 22 '13 at 11:58
-2

Using a ConcurrentHashMap might be a better choice if sahred between threads... The Iterator is not threadsafe and you should create a new iterator insted of using the same between threads.

David
  • 375
  • 4
  • 11