How to delete a key value pair from a HashMap during Iteration in Java - Example tutorial
Suppose you have a Map or Dictionaries like HashMap or Hashtable, which contains key-value pairs like books and their prices, and you want to delete all books whose prices are greater than 40 USD, how do you that in Java? This is one of the most common scenarios while developing Java application and many Java programmer, will say that they will iterate over Map and check each entry and then use the remove(Object key) or remove(Object key, Object value) methods from java.util.Map to delete any mapping where the value is greater than 40 USD. Though the approach is right, the answer is wrong.
Yes, we'll iterate over Map to check each value but we'll not use the two remove() methods from java.util.Map interface because they will throw ConcurrentModficationException when you call them to remove mapping during iteration.
Instead, we'll use the Iterator.remove() method to delete any key-value pair, where the value is greater than 40 USD.
The Iterator is a common interface which allows you to go through each element of any Collection class including Map.
Though, since Map doesn't implement Collection interface, you just cannot directly get an iterator from Map, but you can always get a view of Map and then get the iterator from those set e.g. set of keys by calling keySet() method.
It returns set because of java.util.Map doesn't allow duplicate keys. If you are not familiar with basic Collection classes in Java like List, Set, and Map, I suggest you to first go through a comprehensive course in Java likeThe Complete Java MasterClass on Udemy. It explains all those fundamentals quite well.
How to delete an entry from a HashMap during Iteration
You can also get a collection of values by calling values() method because values can repeat in Map, and set of entries by calling the entrySet()method. These Set and Collection are backed by the actual map, hence any modification you do on this view will reflect in the original map.Apart from navigation method e.g. hasNext() and next(), Iterator also contains a remove() method which is used to remove the current element from the Collection you are iterating. This method should be used to delete any entry or key-value pair from the map during iteration.
Even though, java.util.Map interface provides a couple of overloaded version of remove() method e.g. remove(Object key) which can be used to remove a mapping by key and remove(Object key, Object value) to remove a key-value pair, they cannot be used when you are iterating over map using Iterator or enhanced for loop (remember Java 1.5 for each loop is internally implemented using Iterator itself).
If you use them to remove mapping your code will throw ConcurrentModfiicationException, even if you are running your code on single thread environment.
Yes, the word concurrent has confused many Java programmer from years, who get scared of getting this exception in a multithreading environment, but here concurrent is used in conjunction with iteration + any other operation which modifies the structure of Collection.
In short, always use Iterator's remove() method to remove a key-value pair from Map while iterating over it. Here are exact steps to remove a key-value pair from java.util.Map
1) Get a Set of keys or Set of entries by calling keySet() or entrySet() method of java.util.Map
2) Get the Iterator from the key set or entry set.
3) Iterate over key set or entry set.
4) Check each value, if it satisfies criterion call iterator.remove() method
Once you finish iteration, the mappings which satisfy removal criterion should have been removed. Though, if you want to learn more about Iterator and in general Collection framework, I suggest you go throughJava Fundamentals: Collections by Richard Richard Warburton on Pluralsight. It's a specialized course on Collections and covers the topic in-depth.
Btw, you would need a Pluralsight membership to access this course, which costs around $29 monthly or $299 annually (you can get now in $199, 33% discount ). I have one and I also suggest all developers have that plan because Pluralsight is like NetFlix for Software developers.
It has more than 5000+ good quality courses on all latest topics. Since we programmers have to learn new things every day, an investment of $299 USD is not bad.
Btw, it also offers a 10-day free trial without any obligation which allows you to watch 200 hours of content. You can watch this course for free by signing for that trial.
Now, let's see a complete Java program to remove entries from Map.
Java Program to remove key-value pairs while traversing a Map
In this program, I have a map of Java books and their prices, taken from Amazon.com. Basically, we have 5 best Java books and their prices and our task is to remove all books whose price is higher than 39 dollars. In order to do that, I'll iterate over Map and call Iterator.remove() method after checking the price of the book.I am using entrySet() for traversing Map because it gives you entry, which contains both key and value. If you need both, then this is faster than traversing Map using a set of keys, because you need to perform a lookup to get the value.
If the price of the book is higher than 39 USD then we remove the book by calling the iterator's remove() method. We get the price by calling the getValue() method.
import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; /* * Java Program to remove key value pair from Map while * iteration. */ public class Demo { public static void main(String[] args) throws Exception { // create a Map to demonstrate example Map<String, Double> priceMap = new HashMap<String, Double>(); // add some mapping e.g. popular Java books and their prices priceMap.put("Effective Java", 41.79); priceMap.put("Head First Java", 29.02); priceMap.put("Java Concurrency In Practice", 30.67); priceMap.put("Java SE 8 for Really Impatient", 31.99); priceMap.put("Head First Design Pattern", 39.05); // let's remove all books which are greater than 39.00 USD from map // get a set of entries Set<Entry<String, Double>> setOfEntries = priceMap.entrySet(); // get the iterator from entry set Iterator<Entry<String, Double>> iterator = setOfEntries.iterator(); // iterate over map while (iterator.hasNext()) { Entry<String, Double> entry = iterator.next(); Double value = entry.getValue(); if (value.compareTo(Double.valueOf(39.00)) > 0) { System.out.println("removeing : " + entry); // priceMap.remove(entry.getKey()); // wrong - will throw // ConcurrentModficationException // priceMap.remove(entry.getKey(), entry.getValue()); // wrong - will // throw error iterator.remove(); // always use remove() method of iterator } } } } Output Removing: Head First Design Pattern=39.05 Removing: Effective Java=41.79
From the output, you can see that both Effective Java and Head First Design Patterns are removed because their price is higher than 39 USD but Map still contains other Java books e.g. Head First Java, Java Concurrency in Practice, and Java SE 8 for Really Impatient.
Our code is also free from ConcurrentModificaitonException becuase we are using Iterator's remove() method. If you uncomment the line which uses Map.remove() method then the code will throw ConcurrentMdofiicationException, as shwon below:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextNode(HashMap.java:1437)
at java.util.HashMap$EntryIterator.next(HashMap.java:1471)
at java.util.HashMap$EntryIterator.next(HashMap.java:1469)
at Demo.main(Demo.java:34)
Don't confuse why you are getting concurrent modification exception even if just one thread is modifying the collection. The concurrent here doesn't mean multi-threading but simultaneously performing two operations e.g. iteration and removal.
That's all about how to remove a key-value pair from Map during traversal. You should always use Iterator's remove() method to remove any mapping from the map while iterating over it to avoid any error. Use of Map.remove() method is prohibited during traversal because it throws ConcurrentMdoficiationException.
Further Learning
The Complete Java MasterClass
What's New in Java 8
Refactoring to Java 8 Streams and Lambdas Self- Study Workshop
Other Java Collection tutorials you may like
How to sort a Map by keys and values in Java? (tutorial)
How to sort an ArrayList in ascending and descending order in Java? (tutorial)
Difference between ArrayList and HashSet in Java? (answer)
The difference between TreeMap and TreeSet in Java? (answer)
The difference between HashMap and ConcurrentHashMap in Java? (answer)
The difference between HashMap and LinkedHashMap in Java? (answer)
The difference between Hashtable and HashMap in Java? (answer)
The difference between HashSet and TreeSet in Java? (answer)
The difference between ArrayList and LinkedList in Java? (answer)
The difference between Vector and ArrayList in Java? (answer)
Difference between EnumMap and HashMap in Java
Thanks for reading this article so far. If you like this article then please share with your friends and colleagues. If you have any question or feedback then please drop a comment.
Join the conversation