5

i have this hashmap

HashMap <Integer,Integer> H = new HashMap <Integer,Integer>();

and when i try to remove the key from HashMap i recive this error

**Exception in thread "main" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:922)
at java.util.HashMap$KeyIterator.next(HashMap.java:956)
at Livre.montantTotal(Livre.java:42)** 

this is my code

for (int e : H.keySet()){
    H.put(e, H.get(e)-1);
    if (H.get(e) == 0){
        H.remove(e);
    }
}   
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
Lyrical
  • 81
  • 1
  • 1
  • 3
  • You can't modify a collection while you're iterating through it. – Fernando Matsumoto Oct 01 '15 at 00:11
  • well, you can use the remove() method on an Iterator (so expand for loop into a proper Iterator), but you wont be able to add to the collection while you are iterating it. perhaps collect up the additions in a list and add them at the end. – slipperyseal Oct 01 '15 at 00:18
  • @FernandoMatsumoto Mmm, it is related but not really duplicate because here it's a map – Dici Oct 01 '15 at 00:18
  • why is everyone voting this down? it might be a duplicate but its a common issue – slipperyseal Oct 01 '15 at 00:20

3 Answers3

6

You are getting this error because you are trying to remove the element and rearrange the hashmap while its already in use (while looping through it).

To loop through an collection objects in Java, you have an Iterator class which can solve your problem. That class has a remove() method to remove a key pair value from HashMap.

Possible duplicate of How to remove a key from HashMap while iterating over it? and
iterating over and removing from a map

EDIT:

Try this code on Java 7 and earlier versions:

Map<String, String> map = new HashMap<String, String>() {
  {
    put("test", "test123");
    put("test2", "test456");
  }
};

for(Iterator<Map.Entry<String, String>> it = map.entrySet().iterator(); it.hasNext(); ) {
  Map.Entry<String, String> entry = it.next();
  if(entry.getKey().equals("test")) {
    it.remove();
  }
}

In Java 8, you can try this:

map.entrySet().removeIf(e-> <boolean expression> );
Community
  • 1
  • 1
Kesavamoorthi
  • 959
  • 2
  • 11
  • 21
  • Upvoting because you cannot comment, but this should be a comment if you had enough rep. If you included a full answer instead of just links to other questions, it would make a better answer – Dici Oct 01 '15 at 00:20
  • The Java 8 addition is great because this is one of the recent good changes on the `Map` API people need to know about. It was worth telling you to improve your answer, and upvoting you :) – Dici Oct 01 '15 at 00:44
3

You need to use an Iterator to remove from a collection while iterating over it.

for (Iterator<Map.Entry<Integer, Integer>> i = H.entrySet().iterator(); i.hasNext();) {
    Map.Entry<Integer, Integer> e = i.next();
    int v = e.getValue();
    if (v == 1)
        i.remove();
    else
        e.setValue(v - 1);
}

From the Documentation for HashMap.EntrySet() (https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html)

The set is backed by the map, so changes to the map are reflected in the set, and vice-versa.

Paul Boddington
  • 37,127
  • 10
  • 65
  • 116
0

You can't change something while you're iterating through it. When you change the HashMap, you change it's keySet too, and since you're iterating through that, Java throws an error. What you might have to do is add every key that needs to be removed to a separate list, then iterate through that list afterward.

Like this:

ArrayList<Integer> otherList = new ArrayList<>();
for(int e : H.keySet()){
    h.put(e, H.get(e) - 1);
    if(H.get(e) == 0)
        otherList.add(e);
}

for(int e : otherList){
    H.remove(e);
}
ddsnowboard
  • 922
  • 5
  • 13
  • 2
    According to the doc, it is possible to remove items from the set using `Iterator.remove`, and the changes will be reflected to the map. I don't think this is thread-safe though – Dici Oct 01 '15 at 00:16
  • no less thread safe than modifying maps from multiple threads anyway. – slipperyseal Oct 01 '15 at 00:44