Backend Development 8 min read

Understanding Why HashMap.keySet() Traverses Twice and How entrySet() Provides a More Efficient Iteration

This article explains the internal mechanics of Java's HashMap traversal, showing that keySet() incurs two passes due to iterator creation while entrySet() (or Map.forEach) iterates in a single pass, and it demonstrates the process through decompiled source code and concrete examples.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Understanding Why HashMap.keySet() Traverses Twice and How entrySet() Provides a More Efficient Iteration

HashMap is a widely used Java container, and its traversal methods include using an Iterator, keySet() with an enhanced for‑loop, entrySet() with an enhanced for‑loop, and Java 8+ lambda/stream APIs.

The Alibaba Development Manual recommends using entrySet for traversal and, in Java 8, Map.forEach() , because the number of traversal passes differs: keySet requires two passes, while entrySet needs only one.

Why does keySet traverse twice? The first pass creates an Iterator from the key set, and the second pass retrieves each value from the map using the keys.

Example code using keySet() :

public class Test {
    public static void main(String[] args) {
        Map
map = new HashMap<>();
        map.put("k1", "v1");
        map.put("k2", "v2");
        map.put("k3", "v3");
        for (String key : map.keySet()) {
            String value = map.get(key);
            System.out.println(key + ":" + value);
        }
    }
}

The compiled class shows that the enhanced for‑loop is transformed into an iterator:

public class Test {
    public static void main(String[] args) {
        Map
map = new HashMap();
        map.put("k1", "v1");
        map.put("k2", "v2");
        map.put("k3", "v3");
        Iterator var2 = map.keySet().iterator();
        while (var2.hasNext()) {
            String key = (String) var2.next();
            String value = (String) map.get(key);
            System.out.println(key + ":" + value);
        }
    }
}

The keySet() method returns a KeySet object whose iterator() creates a KeyIterator instance:

public final Iterator
iterator() { return new KeyIterator(); }

KeyIterator extends HashIterator and implements Iterator , providing a next() method that returns nextNode().key .

The abstract HashIterator constructor contains a do‑while loop that advances to the first non‑null entry in the internal table, which is the actual traversal step:

HashIterator() {
    expectedModCount = modCount;
    Node
[] t = table;
    current = next = null;
    index = 0;
    if (t != null && size > 0) {
        do {} while (index < t.length && (next = t[index++]) == null);
    }
}

Thus, using keySet() implicitly performs two traversals: one to obtain the iterator and another to fetch each value, whereas entrySet() (or Map.forEach() ) accesses entries directly in a single pass.

Summary points:

Iterating with keySet() internally calls iterator() .

iterator() creates a KeyIterator object.

KeyIterator extends HashIterator , whose constructor loops to locate the first non‑empty entry.

This double‑pass behavior explains why entrySet() is recommended for efficient HashMap traversal.

BackendJavaHashMapiterationkeySetentrySet
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.