java.util.ConcurrentModificationException when removing elements from a hashmap
Solution 1
Your for-loop gets the map.entrySet and uses the iterator on it to work through the map entries (this version of the for-loop requires an Iterable, it gets the iterator from the Iterable). When you are using an iterator on a map, but remove things from the map without using that iterator, you get the ConcurrentModificationException. That is the map telling the iterator that it's out of date.
You can write a for loop using the iterator explicitly, like this:
for (Iterator<Map.Entry<String, Integer> it = map.entrySet().iterator();
it.hasNext();) {
and use the iterator's remove method when you need to delete an entry.
Solution 2
You are calling remove
while you're iterating over the Map
. This line, the enhanced for loop, runs an Iterator
implicitly:
for(Map.Entry<String,Integer> entry : map.entrySet() )
When an Iterator
detects that its collection is modified, it throws a ConcurrentModificationException
. However, you can call remove()
on the Iterator
itself without that exception being thrown. Use an Iterator
explicitly:
Iterator<Map.Entry<String, Integer>> itr = map.entrySet().iterator();
while(itr.hasNext())
{
Map.Entry<String, Integer> entry = itr.next();
if(entry.getValue().intValue() == 2)
{
System.out.println("Key : "+entry.getKey()+" Removed.");
itr.remove(); // Call Iterator's remove method.
}
}
Solution 3
You cannot remove an element from a map which you are currently iterating over. You could define an iterator, or you could make a few simple modifications to your code within the block for case 3.
case 3:
System.out.print("Enter Value to remove : ");
value = input.nextInt();
if(map.containsValue(new Integer(value)))
{
Map.Entry<String,Integer> foo = null;
for(Map.Entry<String,Integer> entry : map.entrySet() )
if(entry.getValue().intValue() == value)
foo = entry;
System.out.println("Key : "+foo.getKey()+" Removed.");
map.remove(foo.getKey());
}
break;
Solution 4
Just Use Iterator class to remove the Iterating Element as
for (Iterator<Map.Entry<String, Integer> it = map.entrySet().iterator();
while(it.hasNext()) {
Map.Entry<String, Integer> e= itr.next();
key = e.getKey();
Value = e.getValue();
//Your Other Code Here
it.remove(); //It removes the current Itertaion from Map
}
![cyberpirate92](https://i.stack.imgur.com/Hhpf2.jpg?s=256&g=1)
cyberpirate92
Other than coding, I also enjoy playing chess, reading books and occasionally blogging about stuff. Do Checkout my blog https://medium.com/@ravi_theja :)
Updated on July 09, 2022Comments
-
cyberpirate92 almost 2 years
I am learning about
HashMap
class and wrote this simple program. this code works good for adding elements to the hashmap and while removing elements from the hashmap , I am encounteringjava.util.ConcurrentModificationException
for example here is a copy of my terminal,[ravi@doom test]$ java TestHashMap .....MENU..... 1. Add 2. remove key 3. remove value 4. display 7. Exit Your choice :1 Key : A Value : 1 Key/Value : (A,1) added to storage. .....MENU..... 1. Add 2. remove key 3. remove value 4. display 7. Exit Your choice :1 Key : B Value : 2 Key/Value : (B,2) added to storage. .....MENU..... 1. Add 2. remove key 3. remove value 4. display 7. Exit Your choice :1 Key : C Value : 3 Key/Value : (C,3) added to storage. .....MENU..... 1. Add 2. remove key 3. remove value 4. display 7. Exit Your choice :1 Key : D Value : 4 Key/Value : (D,4) added to storage. .....MENU..... 1. Add 2. remove key 3. remove value 4. display 7. Exit Your choice :4 ( D , 4 ); ( A , 1 ); ( B , 2 ); ( C , 3 ); .....MENU..... 1. Add 2. remove key 3. remove value 4. display 7. Exit Your choice :2 Key to REMOVE : D Pair (D,4) Removed. .....MENU..... 1. Add 2. remove key 3. remove value 4. display 7. Exit Your choice :4 ( A , 1 ); ( B , 2 ); ( C , 3 ); .....MENU..... 1. Add 2. remove key 3. remove value 4. display 7. Exit Your choice :3 Enter Value to remove : 2 Key : B Removed. Exception in thread "main" java.util.ConcurrentModificationException at java.util.HashMap$HashIterator.nextEntry(HashMap.java:922) at java.util.HashMap$EntryIterator.next(HashMap.java:962) at java.util.HashMap$EntryIterator.next(HashMap.java:960) at TestHashMap.start(TestHashMap.java:60) at TestHashMap.main(TestHashMap.java:87) ABRT problem creation: 'success'
code:
import java.util.HashMap; import java.util.Map; import java.util.Scanner; class TestHashMap { private Map<String,Integer> map; public TestHashMap() { map = new HashMap<String,Integer>(); } public void displayMenu() { System.out.println(".....MENU....."); System.out.println("1. Add"); System.out.println("2. remove key"); System.out.println("3. remove value"); System.out.println("4. display"); System.out.println("7. Exit"); System.out.print("Your choice :"); } public void start() { Scanner input = new Scanner(System.in); int menuChoice,value; String key; while(true) { displayMenu(); menuChoice = input.nextInt(); switch(menuChoice) { case 1: System.out.print("\n Key : "); input.nextLine(); key = input.nextLine(); System.out.print("\n Value : "); value = input.nextInt(); map.put(key,new Integer(value)); System.out.println("Key/Value : ("+key+","+value+") added to storage."); break; case 2: System.out.println("Key to REMOVE : "); input.nextLine(); key = input.nextLine(); Integer v = map.get(key); if(v == null) System.out.println("No value exists for key "+key); else { map.remove(key); System.out.println("Pair ("+key+","+v.intValue()+") Removed."); } break; case 3: System.out.print("Enter Value to remove : "); value = input.nextInt(); if(map.containsValue(new Integer(value))) { for(Map.Entry<String,Integer> entry : map.entrySet() ) { if(entry.getValue().intValue() == value) { System.out.println("Key : "+entry.getKey()+" Removed."); map.remove(entry.getKey()); } } } break; case 4: for(Map.Entry<String,Integer> entry : map.entrySet() ) { System.out.println("( "+entry.getKey()+" , "+entry.getValue()+" );"); } break; case 7: input.close(); System.exit(0); default: System.out.println("Invalid Choice !"); } } } public static void main(String args[]) { TestHashMap thm = new TestHashMap(); thm.start(); } }
UPDATE: working code
thanks to both (rgettman,Nathan Hughes) of you.
import java.util.HashMap; import java.util.Map; import java.util.Scanner; import java.util.Iterator; class TestHashMap { private Map<String,Integer> map; public TestHashMap() { map = new HashMap<String,Integer>(); } public void displayMenu() { System.out.println(".....MENU....."); System.out.println("1. Add"); System.out.println("2. remove key"); System.out.println("3. remove value"); System.out.println("4. display"); System.out.println("7. Exit"); System.out.print("Your choice :"); } public void start() { Scanner input = new Scanner(System.in); int menuChoice,value; String key; while(true) { displayMenu(); menuChoice = input.nextInt(); switch(menuChoice) { case 1: System.out.print("\n Key : "); input.nextLine(); key = input.nextLine(); System.out.print("\n Value : "); value = input.nextInt(); map.put(key,new Integer(value)); System.out.println("Key/Value : ("+key+","+value+") added to storage."); break; case 2: System.out.println("Key to REMOVE : "); input.nextLine(); key = input.nextLine(); Integer v = map.get(key); if(v == null) System.out.println("No value exists for key "+key); else { map.remove(key); System.out.println("Pair ("+key+","+v.intValue()+") Removed."); } break; case 3: System.out.print("Enter Value to remove : "); value = input.nextInt(); if(map.containsValue(new Integer(value))) { for (Iterator<Map.Entry<String, Integer>> it = map.entrySet().iterator();it.hasNext();) { Map.Entry<String,Integer> x = it.next(); if(x.getValue().intValue() == value) { key = x.getKey(); it.remove(); System.out.println("Key : "+key+" Removed."); } } } break; case 4: for(Map.Entry<String,Integer> entry : map.entrySet() ) { System.out.println("( "+entry.getKey()+" , "+entry.getValue()+" );"); } break; case 7: input.close(); System.exit(0); default: System.out.println("Invalid Choice !"); } } } public static void main(String args[]) { TestHashMap thm = new TestHashMap(); thm.start(); } }
-
Julien almost 9 yearsI prefer the version that uses
while(it.hasNext())
, as for loops are normally used for loop where the number of iteration are known in advance. Well I've been told so years ago at uni. -
Nathan Hughes almost 9 years@Julien: sure, pretty much the same thing; only difference is the for loop keeps the scope of the iterator variable local to the for-block.