ConcurrentModification exception with Map and Hashtable
In my application, I used a map to store POJOs. As per requirement, I need to iterate over a set of map keys and remove objects that don't need any changes.
Consider 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 the above code, I am getting a ConcurrentModificationException when trying to retrieve a user object after deleting the object.
Can anyone tell me why this is happening?
I have not used multithreading. So I can't figure out where it was throwing the ConCurrentModification exception from.
Even I tried with HashMap and Hashtable, but the problem still exists.
source to share
from where it threw a ConCurrentModification exception.
It was coming from the line where you are trying to remove the item from Map
, iterating over it KeySet
.
if(!user.isActive()){
removeUser.remove(key); // This is the problem
}
You shouldn't be doing this. If you want to change your Collection
or Map
, use iterator
.
Take a look at this very nice post - efficient-equivalent-for-removing-elements-while-iterating-the-collection , which explains the problems that can arise when changing the collection you are iterating into.
Here is 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}
source to share
If you are using ConcurrentHashMap, it will not throw ConcurrentModificationException.
A more general solution is to use an Iterator to do 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 keySet()
it as you are only interested invalues()
source to share
use an iterator to iterate over Set and use iterator.remove()
, you cannot remove items from a collection by iterating over it. you will get ConcurrentModification exception
root reason for your exception:
removeUser.remove(key);
iterating over your set using this iterator.
Iterator<String> itr = keySet .iterator();
while(itr.hasNext){
String s = itr.next();
itr.remove(); // to remove the current element.
}
source to share