user1769197
user1769197

Reputation: 2213

Java: Why doesn't the following construction throw ConcurrentModificationException?

I have the following structure:

public class Object1{

    private HashMap<Double, Node> myMap;
    ...

    public void cancelItem(Item o) {
            for(Map.Entry<Double, Node> nn: myMap.entrySet()) {
                if(nn.getValue().containItem(o)) {
                    nn.getValue().cancelItemFromNode(o);
                }
            }
     }
}

and another class

public class Node{
    private HashMap<String,Item> itemIDHashMap; 

    public boolean containItemID(Item o) {
            return itemIDHashMap.containsKey(o.getItemID());
    }

    public void cancelItemFromNode(Item o) {
        if(itemIDHashMap.containsKey(o.getItemID())) {
            itemIDHashMap.remove(o.getItemID());
        } 
    }
}

So the code above does this: whenever Object1's cancelItem method is invoked, it iterates the myMap hashmap to find a Node , which contains another hashmap itemIDHashMap , and check whether the itemIDHashMap contains the same item ID, if it does, then remove the item from itemIDHashMap.

Now, from my understanding since I am iterating over the hashmap myMap without using iterator and I am trying to remove elements from the hashmap, why does it not throw a ConcurrentModificationException at runtime?

UPDATE: Apologies. I forgot to clarify. I understand I am in fact iterating over one hashmap but removing key value pair from another hashmap. However, in my design above, I believe I am still modifying the content of Node , which is still part of the myMap hashmap because I am removing Item key value pair from the hashmap of Node class. So technically , I am still modifying the contents of the myMap hashmap ?

Upvotes: 2

Views: 62

Answers (1)

Eran
Eran

Reputation: 393841

You are iterating over the entry set of one Map - myMap - but remove entries from different Maps - itemIDHashMap. Therefore there's no reason for ConcurrentModificationException to be thrown.

Removing entries from the itemIDHashMap instance variable of a Node, which is a value of the Map you are iterating over, makes no structural changes in that Map, and is therefore allowed.

Here are some relevant quotes from the HashMap Javadoc, which explain when ConcurrentModificationException is thrown while iterating over the entries of the Map:

A structural modification is any operation that adds or deletes one or more mappings; merely changing the value associated with a key that an instance already contains is not a structural modification.

...

The iterators returned by all of this class's "collection view methods" are fail-fast: if the map is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove method, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

entrySet() is one of the mentioned "collection view methods".

Upvotes: 7

Related Questions