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 an 8% hike, now our task is to update this Map, so each worker's 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 the 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 an 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.
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 an 8% hike, now our task is to update this Map, so each worker's 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 the 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 an 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 the process, then this is the best way, as you get both key and value wrapped in entry, you don't need to call the 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 the 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 need a 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 a 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 an 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 :
Here is full Java code, which you can run in your Java IDE or by using the command prompt. Just copy this code and paste into a Java source file with the name MapLoopDemo and save it as .java extension, compile it using "javac" and run it using "java" command.
That's all about how to loop through Map in Java. Traversing is a common task in any programming language and many of them provide 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 a more expressive way to do the common tasks in the collection using lambda expressions and bulk data operations.
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
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 provide 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 a more expressive way to do the common tasks in the collection using lambda expressions and bulk data operations.
For examples task like looping through a List, filtering certain elements, transforming one object to another, and reducing them into one value will be very easy. So far, you can use the 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 the Java Collection framework? check out these amazing articles
- Difference between HashMap and Hashtable in Java? (answer)
- How do you sort a Map on keys and values in Java? (answer)
- Array length vs ArrayList size()? (read here)
- How do you remove() elements from ArrayList in Java? (answer)
- How HashSet works internally in Java? (answer)
- 10 ways to use ArrayList in Java? (see here)
- Difference between Set, List, and Map in Java? (answer)
- When to use ArrayList over LinkedList in Java? (answer)
- Difference between HashSet and HashMap in Java? (answer)
- Difference between HashMap and LinkdHashMap in Java? (answer)
- When to use HashSet vs TreeSet in Java? (answer)
- How to sort ArrayList in increasing order in Java? (answer)
- Best way to loop through ArrayList in Java? (answer)
- Difference between ConcurrentHashMap vs HashMap in Java? (answer)
Thanks for sharing, very useful blog
ReplyDeleteWhile 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.
ReplyDeleteIn 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