How to iterate over a map
Short answer
entrySet() returns "key — value" pairs:
void main() {
Map<String, Integer> stock = new LinkedHashMap<>();
stock.put("apples", 10);
stock.put("pears", 4);
for (Map.Entry<String, Integer> entry : stock.entrySet()) {
IO.println(entry.getKey() + " = " + entry.getValue());
}
}Output:
apples = 10
pears = 4The forEach method
The lambda in forEach() receives the key and the value directly:
void main() {
var stock = new TreeMap<>(Map.of("pears", 4, "apples", 10));
stock.forEach((fruit, count) -> IO.println(fruit + ": " + count));
}Output:
apples: 10
pears: 4Keys or values only
keySet() returns the keys, values() the values:
void main() {
var prices = new TreeMap<>(Map.of("tea", 3, "cake", 12));
IO.println(prices.keySet());
IO.println(prices.values().stream().mapToInt(Integer::intValue).sum());
}Output:
[cake, tea]
15Iteration order
HashMap does not guarantee any order. LinkedHashMap keeps the insertion order, TreeMap sorts the keys.
Common mistake
Removing entries from a Map inside a for-each loop. This causes a ConcurrentModificationException:
void main() {
var stock = new HashMap<>(Map.of("apples", 0, "pears", 4, "plums", 0));
for (String key : stock.keySet()) {
if (stock.get(key) == 0) {
stock.remove(key);
}
}
}Output:
Exception in thread "main" java.util.ConcurrentModificationExceptionUse removeIf(): stock.values().removeIf(count -> count == 0).
Functions used in this recipe
- Map.entrySet() — Returns all key and value pairs for iteration.
- Map.forEach() — Runs an action for every pair of a map.
- Map.keySet() — Returns the set of all keys of a map.
- Map.values() — Returns a collection of all values of a map.