Gunjan Shah
Gunjan Shah

Reputation: 5168

ConcurrentModification Exception with Map and Hashtable

In my application I have used a Map to store POJO objects. As per the requirement I need to iterate over the keySet of the Map and remove objects which dont need any modification.

Conside the code below:

 public void remove(Map<String,User> removeUser){
  Set<String> keySet = removeUser.keySey();
  User user = null;

  for(String key : keySet){
      user = (user) removeUser.get(key);

       if(!user.isActive()){
                removeUser.remove(key);
       }
  }

 }

Here in above code, I am getting ConcurrentModificationException when I try to fetch User object after Object removal.

Can anyone tell me why it's happening?

I have not used multi threading.So not able to understand, from where it generated ConCurrentModification Exception.

Even I tried with HashMap and Hashtable, but the problem still exist.

Upvotes: 2

Views: 4480

Answers (3)

PermGenError
PermGenError

Reputation: 46428

use an iterator to iterate over your Set and use iterator.remove(), you cant remove elements from your collection while iterating over it.you'd get a ConcurrentModification Exception

root cause of your Exception is here:

        removeUser.remove(key);

iterate over your set like this, using an iterator.

Iterator<String> itr = keySet .iterator();
while(itr.hasNext){
   String s = itr.next();
   itr.remove(); // to remove the current element.
 }

Upvotes: 2

Rohit Jain
Rohit Jain

Reputation: 213351

from where it generated ConCurrentModification Exception.

It came from the line where you are trying to remove the element from your Map while iterating over its KeySet.

if(!user.isActive()){
     removeUser.remove(key);  // This is the problem
}

You should not do that. If you want to modify your Collection or Map, use an iterator.


See this very nice post - efficient-equivalent-for-removing-elements-while-iterating-the-collection explaining the problems that can come while modifying the collection you iterate upon.


Here's a simple code explaining how you can use it here: -

    Map<String, Integer> map = new HashMap<String, Integer>() {
        {
            put("a", 1);
            put("b", 2);
            put("c", 3);
        }
    };

    Iterator<String> iterate = map.keySet().iterator();

    while  (iterate.hasNext()) {
        int i = map.get(iterate.next());

        if(i > 1) {
            iterate.remove();
        }
    }

    System.out.println(map);

OUTPUT: -

{a=1}

Upvotes: 11

Peter Lawrey
Peter Lawrey

Reputation: 533750

If you use ConcurrentHashMap it won't produce a ConcurrentModificationException.

The more general solution is to use the Iterator to do the remove().

public void removeInactiveUsers(Map<String, User> map) {
    for (Iterator<User> iter = map.values().iterator(); iter.hasNext(); ) 
        if (!user.isActive())
            iter.remove();
}

Note: you don't need the keySet() as you are only interested in the values()

Upvotes: 5

Related Questions