2

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.

halfer
  • 19,824
  • 17
  • 99
  • 186
Gunjan Shah
  • 5,088
  • 16
  • 53
  • 72

3 Answers3

11

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}
Community
  • 1
  • 1
Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
  • Thanks for the answer. Good Explanation. I referred this link : http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html. Here they have given good explanation about ConcurrentModificationException on Structure change of a map. – Gunjan Shah Nov 19 '12 at 12:19
  • @GunjanShah.. Yeah of course that's the documentation link. And has a good and concise explanation on this stuff. Please keep on referring documentation to learn about the various methods in Java. :) – Rohit Jain Nov 19 '12 at 12:23
  • Ahhh! I entered that on my iphone from memory. I was sure entry had remove()! crap – Bohemian Nov 19 '12 at 12:32
  • @Bohemian.. haha :) No problem.. It happens sometimes. Its difficult to remember every method of every class though. Cheers :) – Rohit Jain Nov 19 '12 at 12:35
5

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()

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
2

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.
 }
PermGenError
  • 45,977
  • 8
  • 87
  • 106