What it is
A HashMap stores key and value pairs. To work with every pair, you loop over the map. A for-each loop can't take the map itself, so you hand it one of the map's views. The most useful one is entrySet(), which gives one Map.Entry per pair. An entry holds a key and its value, and you read them with getKey() and getValue().
HashMap<String, Integer> stock = new HashMap<>();
stock.put("apples", 5);
stock.put("pears", 2);
for (Map.Entry<String, Integer> entry : stock.entrySet()) {
System.out.println(entry.getKey() + " " + entry.getValue());
}
This prints:
pears 2
apples 5
The entry's type is Map.Entry<String, Integer>: the same two type arguments as the map. The loop body runs once for every key.
Looping over the keys only
When you only need the keys, loop over keySet(). You can still read each value with get:
for (String fruit : stock.keySet()) {
System.out.println(fruit + " " + stock.get(fruit));
}
This prints the same two lines. The entrySet() form is usually better when you need both parts, because each entry already holds its value, so there is no second lookup.
The order is not fixed
A HashMap has no promised order. The entries can come in any order, and the order can change when the map grows. Do not write code that depends on which entry comes first. A total or a count comes out the same in any order, so those are safe things to compute in a loop.
Don't change the keys inside the loop
Adding or removing keys while a loop is running over the map breaks the loop. Java stops with a ConcurrentModificationException. For example, calling stock.put(fruit + "!", 1) inside the keySet() loop above throws it. Decide what to add or remove first, and change the map after the loop.
The lesson's task
The map scores holds four players' points: Ana 12, Ben 7, Cleo 15 and Dan 9. The task is to add up all the points in total and count the players with 10 points or more in count. Both variables start at 0.
for (Map.Entry<String, Integer> entry : scores.entrySet()) {
total += entry.getValue();
if (entry.getValue() >= 10) {
count += 1;
}
}
The three steps are: write the loop with entry as its variable, add entry.getValue() to total, and, below that, add 1 to count when the value is at least 10. With the lesson's code printing both variables afterwards, the output is:
43
2
12 + 7 + 15 + 9 is 43, and only Ana (12) and Cleo (15) reach 10.
Working through the loop
On each turn of the loop, entry is a different pair of the map. On the turn for Ana, entry.getKey() is "Ana" and entry.getValue() is 12, so total grows by 12 and count grows by 1. On the turn for Ben, the value is 7, so total grows by 7 and count stays the same. Whichever order the four players arrive in, the final total and count are the same. That is why these two answers are safe to compute from a HashMap.
Common mistakes
- Using
intas the loop variable's type. An entry is an object, so the variable is aMap.Entry, not a number. - Calling
entry.getValue()when you wanted the key, or the other way round. - Expecting the entries in the order you added them. For that you would need a different map class.
- Adding or removing keys inside the loop.
Key takeaways
for (Map.Entry<K, V> entry : map.entrySet())visits every pair once.getKey()andgetValue()read the two parts of an entry.keySet()gives only the keys.- Rely on totals and counts, not on the order.
