Tuesday, August 13, 2013
Best way to Iterate over each Entry in HashMap in Java | How to loop Map to remove Entries
What is the best way to Iterate over HashMap in Java? and not just HashMap, but any Map implementation including old Hashtable, TreeMap, LinkedHashMap and relatively newer ConcurrentHashMap, is a frequently asked queries from Java Programmers, with some experience under his belt. Well, when it comes to choosing between different ways to iterate over Map in Java, it's you need, which plays an important role. For example, if you just want to iterate over each entry of HashMap, without modifying Map, then iterating over entry set using Java 1.5 foreach loop seems most elegant solution to me. Reason, it just two lines of code using foreach loop and Generics, and by getting set of entries, we get key and value together, without further searching in HashMap. This makes it also fastest way to loop over HashMap in Java. On the other hand, if you want to remove entries, while iterating over HashMap, may be only selective entries, than foreach loop will not help. Though foreach loop internally uses Iterator for traversing elements, It doesn't expose handle to that Iterator, which means you only have remove() method of Map to remove entries. That's not the ideal way, especially if you had to remove lot of entries and that to during Iteration. Your Iterator may also throw ConcurrentModificationException, depending upon it's fail-safe or fail-fast Iterator. E.g. Iterator of ConcurrentHashMap are weekly consistent with actual Map and doesn't throw ConcurrentModificationException. This leaves us with traditional while loop and Iterator combo, for looping HashMap using Map.entrySet() and removing entries.
Here is the code example of Iterating over any Map class in Java e.g. Hashtable or LinkedHashMap. Though I have used HashMap for iteration purpose, you can apply same technique to other Map implementations. Since we are only using methods from java.uti.Map interface, solution is extensible to all kinds of Map in Java. We will use Java 1.5 foreach loop and Iterating over each Map.Entry object, which we get by calling Map.entrySet() method. Remember to use Generics, to avoid type casting. Use of Generics and foreach loop result in very concise and elegant code, as shown below.This code snippet is very handy for iterating HashMap, but has just one drawback, you can not remove entries without risking ConcurrentModificationException. In next section, we will see code using Iterator, which can help you for removal of entries from Map.
One reason for iterating over Map is removing selected key value pairs from Map. This is a general Map requirement and holds true for any kind of Map e.g. HashMap, Hashtable, LinkedHashMap or even relatively new ConcurrentHashMap. When we use foreach loop, it internally translated into Iterator code, but without explicit handle to Iterator, we just can not remove entries during Iteration. If you do, your Iterator may throw ConcurrentModificationException. To avoid this, we need to use explicit Iterator and while loop for traversal. We will still use entrySet() for performance reason, but we will use Iterator's remove() method for deleting entries from Map. Here code example to remove key values from HashMap in Java:
You can see, we are using remove() method from Iterator and not from java.util.Map, which accepts a key object. This code is safe from ConcurrentModificationException.
By the way, here is complete code example, combining both approaches for iterating over HashMap in Java. As I said before, you can use same code snippet to iterate any Map class, we are not using any specific methods from HashMap, code is complete based on Map interface.
That's all about How to Iterator over HashMap in Java. We have seen couple of ways to iterate over each entry, but as I said, best way is to use foreach loop and entry set, if you just need to traverse, without modifying actual Map. It's very elegant for filtering, where you need to create another Map, from actual Map, based on some filtering criterion. Since Map.Entry object holds both key and value, it provides fastest access to them, instead of calling Map.get(key) method, which involves searching in Map.
Related Java Collection Tutorials and Interview Questions from Java67