Wednesday, June 1, 2022

How to Iterate over HashMap in Java? Map.entrySet().iterator() Example

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 query 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 the most elegant solution to me. 

The reason, it just two lines of code using a foreach loop and Generics, and by getting the set of entries, we get key and value together, without further searching in HashMap. This makes it also the 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. For exampole, 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.



Best way to Iterate over HashMap in Java with Example

Here is the code example of Iterating over any Map class in Java like 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.


for(Map.Entry<Integer, String> entry : map.entrySet()){
    System.out.printf("Key : %s and Value: %s %n",
        entry.getKey(), entry.getValue());
}
 
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.



Removing Entries from Map in Java

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 like 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:

Iterator<Map.Entry<Integer, String>> iterator = map.entrySet().iterator();
while(iterator.hasNext()){
   Map.Entry<Integer, String> entry = iterator.next();
   System.out.printf("Key : %s and Value: %s %n", 
             entry.getKey(), entry.getValue());
   iterator.remove(); // right way to remove entries from Map, 
                      // avoids ConcurrentModificationException
}

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.



HashMap Iterator Example

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.


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

/**
 *
 * Best way to iterate over Map in Java, including any implementation like
 * HashMap, TreeMap, LinkedHashMap, ConcurrentHashMap and Hashtable.
 * Java 1.5 foreach loop is most elegant and combined with entry set also
 * gives best performance, but not suitable for removing entries, as you don't have
 * reference to internal Iterator.
 *
 * Only way to remove entries from Map without throwing ConcurrentModificationException
 * is to use Iterator and while loop.
 *
 * @author http://java67.com
 */
public class HashMapIteratorExample {

    public static void main(String args[]) {
     
        // Initializing HashMap with some key values
        Map<Integer, String> map = new HashMap<Integer, String>();
        map.put(1, "Core Java");
        map.put(2, "Java SE");
        map.put(3, "Java ME");
        map.put(4, "Java EE");
        map.put(5, "Java FX");
       
        // Iterate over HashMap using foreach loop
        System.out.println("Java 1.5 foreach loop provides most elegant
                             way to iterate over HashMap in Java");
        for(Map.Entry<Integer, String> entry : map.entrySet()){
            System.out.printf("Key : %s and Value: %s %n", entry.getKey(),
                                                           entry.getValue());
        }
       
        // Better way to loop over HashMap, if you want to remove entry
        System.out.println("Use Iterator and while loop, if you want 
                              to remove entries from HashMap during iteration");
        Iterator<Map.Entry<Integer, String>> iterator = map.entrySet().iterator();
        while(iterator.hasNext()){
            Map.Entry<Integer, String> entry = iterator.next();
            System.out.printf("Key : %s and Value: %s %n", entry.getKey(), 
                                                           entry.getValue());
            iterator.remove(); // right way to remove entries from Map, 
                               // avoids ConcurrentModificationException
        }
    }    
  
}

Output:
Java 1.5 foreach loop provides 
most elegant way to iterate over HashMap in Java
Key : 1 and Value: Core Java
Key : 2 and Value: Java SE
Key : 3 and Value: Java ME
Key : 4 and Value: Java EE
Key : 5 and Value: Java FX
Use Iterator and while loop, 
if you want to remove entries from HashMap during iteration
Key : 1 and Value: Core Java
Key : 2 and Value: Java SE
Key : 3 and Value: Java ME
Key : 4 and Value: Java EE
Key : 5 and Value: Java FX

You can see that, its quite easy, fast, and elegant way to iterate over an HashMap in Java. You get access to all of the entries and then you can extract keys and values without going through get() method of HashMap. 

By the way, this is not the only way to iterate over a HashMap or a Map in Java. Here are 4 more ways to iterate over a Map in Java:

How to Iterate over HashMap in Java? Map.entrySet().iterator() Example


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


8 comments:

  1. In my opinion best way to iterate a Map is by using it's keySet() instead of entrySet() because you often need keys to perform filtering or any kind of processing logic, and only require value on need basis. By using entrySet(), your Set will require more memory as they now hold both key and value.

    ReplyDelete
    Replies
    1. Exactly and when we're iterating over entry set to get key and value . We perform entry.getKey() and entry.getValue() which I believe is O(1) operation. HashMap.get(key) is also an O(1) operation.

      Delete
  2. Nice reference for map manipulation! Thanks!

    ReplyDelete
  3. EXACTLY what I was looking for, and worked like a charm. Thanks, bro!

    ReplyDelete
  4. If you are iterating over Map in JSP, you can use JSTL foreach tag instead of writing for loop in scriptlet, because it's bad to add Java code in JSP due to maintainence reason. It is also voilation of MVC design pattern.

    ReplyDelete
  5. What advantage do you get by using iterator over foreach or advanced for loop? I think advanced for loop is much cleaner and safer, correct me if I am wrong.

    ReplyDelete
    Replies
    1. @Anonymous, Iterator provides remove() method to remove current element during iteration which is not available in case of advanced for loop.

      Delete

Feel free to comment, ask questions if you have any doubt.