Encodera

Thanks for reading!

Donate to the site — we work hard for you.

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 = 4

The 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: 4

Keys 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]
15

Iteration 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.ConcurrentModificationException

Use removeIf(): stock.values().removeIf(count -> count == 0).

Functions used in this recipe

Thanks for reading!

Donate to the site — we work hard for you.