Reputation: 2213
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
Reputation: 393841
You are iterating over the entry set of one Map
- myMap
- but remove entries from different Map
s - 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