How to Remove Entry (key/value) from HashMap while Iterating? Example Tutorial

Can you remove a key while iterating over HashMap in Java? This is one of the interesting interview questions as well as a common problem Java developer face while writing code using HashMap. Some programmer will say No, you cannot remove elements from HashMap while iterating over it. This will fail fast and throw concurrent modification exception. They are right but not completely. It's true that the iterator of HashMap is a fail-fast iterator but you can still remove elements from HashMap while iterating by using Iterator's remove() method. This is the same technique which we have used in past to remove elements while iterating over a List in Java. The key here is not to use the remove() method from Map or List interface to avoid java.util.ConcurrentModfiicationException in Java.

The ConcurrentModificationException comes when you use Map.remove(Object key) to remove a key. Remember, when you remove a key, the mapping itself is removed i.e. both key and value objects are removed from Map and its size reduced by 1.

Here are the exact steps to remove elements from HashMap while Iterating

1. Get sets of keys by calling the Map.keySet() method
2. Get the Iterator from this set by calling iterator() method of the Set interface.
3. Iterate over Map using this Iterator and while loop
4. Remove an entry from a map based on matching key from set e.g. you can compare the key from Set with the item you want to remove by using Iterator.remove() method


Here is an example to remove elements from HashMap while iterating. In this example, I have a Map of various Java and Spring certifications and their cost e.g OCAJP (1Z0-808) cost around 248 US Dollars, same is for OCPJP 8 (1Z0-809), while Spring certifications provided by Pivotal e.g. Spring Professional Certification Exam and Spring Web Application Developer Exam cost around 200 USD each (see here).

While Iterating over Map, I compare key with the OCMJEA (Oracle Certified Master Java Enterprise Architect) and if the key matches then I remove it from the Map. Here, I have used the remove() method of HashMap, hence this program will throw ConcurrentModfiicationException.

import java.util.HashMap;
import java.util.Map;
import java.util.Set;


/*
 * Java Program to remove mapping from HashMap while Iterating
 * using Map.remove(Object key) method
 */
public class Main {

  public static void main(String args[]) {
    
    Map<String, Integer> certificationCost = new HashMap<>();
    certificationCost.put("OCAJP 1Z0-808", 248);
    certificationCost.put("OCPJP 1Z0-809", 248);
    certificationCost.put("Spring Professional Certification Exam", 200);
    certificationCost.put("Spring Web Application Developer Exam", 200);
    certificationCost.put("OCMJEA 1Z0-807", 600);
    
    
    // let's try to remove element from Hashmap using Map.remove(Object key) method
    // this will not work, will throw ConcurrentModfiicationException
    Set<String> setOfCertifications = certificationCost.keySet();
    
    for(String certificaiton : setOfCertifications){
      
      if(certificaiton.contains("OCMJEA")){
        certificationCost.remove(certificaiton);
      }
    }
  }
}

Output
Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.HashMap$HashIterator.nextNode(HashMap.java:1429)
    at java.util.HashMap$KeyIterator.next(HashMap.java:1453)
    at Main.main(Main.java:24)

You can see the Iterator of HashMap throws java.util.ConcurrentModificationException as soon as you try to remove an entry while iterating over Map because the iterator is fail-fast. If this had been a ConcurentHashMap then it won't throw the ConcurrentModficationExcetpion. Now, let's see the correct way to remove an entry from HashMap while iterating over it.




Right way to Remove a key from HashMap while Iterating in Java

Here is the right way to remove a key or an entry from HashMap in Java while iterating over it. This code uses Iterator and its remove() method to delete a key from HashMap. When you remove a key, the value also gets removed from HashMap i.e. it's a shortcut to remove an entry from HashMap in Java.

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;


/*
 * Java Program to remove mapping from HashMap while Iterating
 * using Iterator's remove() method
 */
public class Main {

  public static void main(String args[]) {
    
    Map<String, Integer> certificationCost = new HashMap<>();
    certificationCost.put("OCAJP 1Z0-808", 248);
    certificationCost.put("OCPJP 1Z0-809", 248);
    certificationCost.put("Spring Professional Certification Exam", 200);
    certificationCost.put("Spring Web Application Developer Exam", 200);
    certificationCost.put("OCMJEA 1Z0-807", 600);
    
    // Map - before removing a mapping
    System.out.println("before: " + certificationCost);
    
    // let's use Iterator to remove a key from HashMap while iterating
    Iterator<String> iterator = certificationCost.keySet().iterator();
    
    while(iterator.hasNext()){
      String certification = iterator.next();
      if(certification.contains("OCMJEA")){
        iterator.remove();
      }
    }
    
    // Map - after removing a mapping
    System.out.println("after: " + certificationCost);
  }
}

Output
before: {Spring Professional Certification Exam=200, OCMJEA 1Z0-807=600,
 Spring Web Application Developer Exam=200, OCPJP 1Z0-809=248,
 OCAJP 1Z0-808=248}
after: {Spring Professional Certification Exam=200,
 Spring Web Application Developer Exam=200, OCPJP 1Z0-809=248,
 OCAJP 1Z0-808=248}

From the output you can see that the entry associated with "OCMJEA 1Z0-807" key is removed the Map, there were 4 entries before removal and now there are only three entries remaining. Also, there is no ConcurrentModificationException occurs.



Java 8 Facts
In Java 8 you can use the map.values().removeAll(Collections.singleton(240)); to remove all key/value pairs where value is 240. See Java SE 8 for the Impatient to learn more about new methods added into existing interfaces in JDK 8.

How to Remove Entry (key/value) from HashMap while Iterating?


That's all about how to remove a key or an entry/mapping while iterating over HashMap in Java. You cannot remove an entry while looping over Map but you can remove a key or value while iterating over it. Since Iterator of HashMap is fail-fast it will throw ConcurrentModificationException if you try to remove entry using Map.remove(Object key) method, the right way to remove an entry from the HashMap by using Iterator's remove() method.


Further Reading
Core Java for the Impatient
Java Interview Exposed
25 Java Collection Interview Questions
How HashMap works in Java
How ConcurrentHashMap works in Java
Head First Java 2nd Edition

Thanks for reading this article this far. If you like this tutorial then please share with your friends and colleagues. IF you have any question or feedback then please drop a comment.

No comments:

Post a Comment