3 Examples to Loop Map in Java - Foreach vs Iterator

There are multiple ways to loop through Map in Java, you can either use a foreach loop or Iterator to traverse Map in Java, but always use either Set of keys or values for iteration. Since Map by default doesn't guarantee any order, any code which assumes a particular order during iteration will fail. You only want to traverse or loop through a Map, if you want to transform each mapping one by one. Now Java 8 release provides a new way to loop through Map in Java using Stream API and forEach method. For now, we will see 3 ways to loop through each element of Map. Though Map is an interface in Java, we often loop through common Map implementation like HashMap, Hashtable, TreeMap and LinkedHashMap. By the way, all the ways of traversing Map discussed in this article is pretty general and valid for any Map implementation, including proprietary and third-party Map classes.

What I mean by looping through Map is getting mappings one at a time, processing them and moving forward. Let's say, we have a Map of Workers, after appraisal every worker has got 8% hike, now our task is to update this Map, so each worker object reflects its new, increased salary.

In order to do this task, we need to iterate through Map, get the Employee object, which is stored as the value. Update Worker with a new salary, and move on. Did you ask about saving it back to Map? no need.

When you retrieve values from Map using get() method, they are not removed from Map, so one reference of the same object is always there in Map until you remove it. That's why, you just need to update object, no need to save it back.

By the way, remember to override equals() and hashCode() method for any object, which you are using as key or value in Map. The internal code of  HashMap uses both of these methods to insert and retrieve objects into Map, to learn more see How Map works in Java. Now, Let's see how can we loop through Map in Java.




1) Using for-each loop with Entry Set

The Map provides you a method called entrySet(), which returns a Set of all Map.Entry objects, which are nothing but mapping stored in Map. If you need both key and value to process, then this is the best way, as you get both key and value wrapped in entry, you don't need to call get() method which goes back to Map again to retrieve the value. Now, enhanced for loop of Java 5 makes your job easy, all you need to do is to iterate through that collection as shown in below example :
        Set<Map.Entry<Integer, Worker>> entrySet = workersById.entrySet();
        for (Map.Entry<Integer, Worker> entry : entrySet) {
            Worker worker = entry.getValue();
            System.out.printf("%s :\t %d %n", worker.getName(),
                    worker.getSalary());
        }

2) Using Iterator with KeySet

If you don't require values and only needs key then you can use Map.keySet() method to get a set of all keys. Now you can use Iterator to loop through this Set. If you need value any time, then you need to get(key) method of Map, which returns value from Map. This is an additional trip to map, that's why the previous method is better if you need both. Here is how to loop through Map using iterator and key set in Java :
        Iterator<Integer> itr = workersById.keySet().iterator();
        while (itr.hasNext()) {
            Worker current = workersById.get(itr.next());
            int increasedSalary = (int) (current.getSalary() * 1.08);
            current.setSalary(increasedSalary);
        }


3) Using enhanced foreach loop with values

Now this is the optimal way of looping through Map if you only need values, as it requires less memory than the first approach. Here also we will use enhanced foreach loop to traverse through values, which is a Collection. We can't use plain old for loop with index because Collection doesn't provide any get(index) method, which is only available in List, and it's totally unnecessary to convert Collection to List for iteration only. Here is how to loop Map in Java using enhanced for loop and values method :
Collection<Worker> workers = workersById.values();
        System.out.println("New Salaries of Workers : ");
        for (Worker worker : workers) {
            System.out.printf("%s :\t %d %n", worker.getName(),
                    worker.getSalary());
        }


Complete Java Program to Loop through Map

How to loop a Map in Java with ExampleHere is full Java code, which you can run in your Java IDE or by using the command prompt. Just copy this code and paste in a Java source file with name MapLoopDemo and save it as .java extension, compile it using "javac" and run it using "java" command.

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

/**
 * Java Program to loop through Map in Java. This examples shows three ways of
 * traversing through Map, foreach loop, Iterator with set of keys, entries and
 * values from Map.
 *
 * @author Javin Paul
 */
public class HelloJUnit {

    private static final Map<Integer, Worker> workersById = new HashMap<>();

    public static void main(String args[]) {

        // let's initialize Map for useworkersById.put(76832, new Worker(76832, "Tan", 8000));
        workersById.put(76833, new Worker(76833, "Tim", 3000));
        workersById.put(76834, new Worker(76834, "Tarun", 5000));
        workersById.put(76835, new Worker(76835, "Nikolai", 6000));
        workersById.put(76836, new Worker(76836, "Roger", 3500));

        // looping through map using foreach loop
        // print initial salary of workers
        System.out.println("Initial Salaries of workers");

        Set<Map.Entry<Integer, Worker>> entrySet = workersById.entrySet();

        for (Map.Entry<Integer, Worker> entry : entrySet) {
            Worker worker = entry.getValue();
            System.out.printf("%s :\t %d %n", worker.getName(),
                    worker.getSalary());
        }

        // looping through map using Iterator
        // updating salary of each worker
        Iterator<Integer> itr = workersById.keySet().iterator();
        while (itr.hasNext()) {
            Worker current = workersById.get(itr.next());
            int increasedSalary = (int) (current.getSalary() * 1.08);
            current.setSalary(increasedSalary);
        }

        // how to loop map using for loop
        // looping through values using for loop
        Collection<Worker> workers = workersById.values();
        System.out.println("New Salaries of Workers : ");
        for (Worker worker : workers) {
            System.out.printf("%s :\t %d %n", worker.getName(),
                    worker.getSalary());
        }

    }

    private static class Worker {

        private int id;
        private String name;
        private int salary;

        public Worker(int id, String name, int salary) {
            this.id = id;
            this.name = name;
            this.salary = salary;
        }

        public final int getId() {
            return id;
        }

        public final String getName() {
            return name;
        }

        public final int getSalary() {
            return salary;
        }

        public final void setId(int id) {
            this.id = id;
        }

        public final void setName(String name) {
            this.name = name;
        }

        public final void setSalary(int salary) {
            this.salary = salary;
        }

        @Override
        public String toString() {
            return "Worker [id=" + id + ", name=" + name + ", salary=" + salary
                    + "]";
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + id;
            result = prime * result + ((name == null) ? 0 : name.hashCode());
            result = prime * result + (int) (salary ^ (salary >>> 32));
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            Worker other = (Worker) obj;
            if (id != other.id) {
                return false;
            }
            if (name == null) {
                if (other.name != null) {
                    return false;
                }
            } else if (!name.equals(other.name)) {
                return false;
            }
            if (salary != other.salary) {
                return false;
            }
            return true;
        }
    }
}

Output:
Initial Salaries of workers
Tim :    3000
Tan :    8000
Nikolai :        6000
Tarun :  5000
Roger :  3500
New Salaries of Workers :
Tim :    3240
Tan :    8640
Nikolai :        6480
Tarun :  5400
Roger :  3780

That's all about how to loop through Map in Java. Traversing is a common task in any programming language and many of them provides easier syntax, contrary to that, In Java you need to write a lot of boilerplate code and our functional intent is hidden between boilerplate code. Java 8 is coming up with more expressive way to do common task in collection using lambda expressions and bulk data operations. For examples task like looping through List, filtering certain elements, transforming one object to another and reducing them into one value will be very easy. So far, you can use above examples to loop through your Map in Java. All examples are valid for any Map implementations including HashMap, Hashtable, TreeMap and LinkedHashMap.

Want to learn more about Java Collection framework? check out these amazing articles

  1. Difference between HashMap and Hashtable in Java? (answer)
  2. How do you sort a Map on keys and values in Java? (answer)
  3. Array length vs ArrayList size()?  (read here)
  4. How do you remove() elements from ArrayList in Java? (answer)
  5. How HashSet works internally in Java? (answer)
  6. 10 ways to use ArrayList in Java? (see here)
  7. Difference between Set, List and Map in Java? (answer)
  8. When to use ArrayList over LinkedList in Java? (answer)
  9. Difference between HashSet and HashMap in Java? (answer)
  10. Difference between HashMap and LinkdHashMap in Java? (answer)
  11. When to use HashSet vs TreeSet in Java? (answer)
  12. How to sort ArrayList in increasing order in Java? (answer)
  13. Best way to loop through ArrayList in Java? (answer)
  14. Difference between ConcurrentHashMap vs HashMap in Java? (answer)

3 comments:

  1. Thanks for sharing, very useful blog

    ReplyDelete
  2. While looping over Map you must remember that Map doesn't guarnatee any order, except TreeMap which guaranteeds sorting order and LinkedHashMap which keeps entries in the order they were inserted into Map. Other than that no Map guarantee any order, not even HashMap. For simple read only iteration the techniques you mentioned is sufficient, especially the one which gets entrySet() and then loop over Map using foreach loop. But, if you have to remove entries during iteration, there is no choice other than using Iterator. Also note, since HashMap is not synchronized, you may be iterating over stale mappings if there is another thread which is modifying Map in background. ConcurrentModificationException is also on the cards.

    ReplyDelete
  3. In this code worker object we are not used as key then I didn't understand overriding of hashcode and equals in Worker object.Please correct me if I am wrong

    ReplyDelete