Fundamentals 8 min read

Why Does HashMap.keySet() Iterate Twice? Uncover the Hidden Iterator Mechanics

This article examines Java HashMap traversal techniques, compares keySet, entrySet, iterator and stream approaches, explains why keySet appears to iterate twice by revealing its internal iterator implementation, and presents code examples and decompiled snippets to illustrate the underlying mechanisms.

Architect's Tech Stack
Architect's Tech Stack
Architect's Tech Stack
Why Does HashMap.keySet() Iterate Twice? Uncover the Hidden Iterator Mechanics

HashMap Traversal Methods

HashMap is a widely used Java container; common traversal methods include Iterator, keySet(), entrySet(), and Java 8 streams.

Recommendation from the Alibaba Development Manual

The manual recommends using entrySet for traversal, and in Java 8, Map.forEach(), because it reduces the number of iterations.

Why keySet Appears to Iterate Twice

keySet

traversal involves two passes: converting the key set to an Iterator and then fetching each value.

Example code using keySet:

public class Test {
    public static void main(String[] args) {
        Map<String, String> 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);
        }
    }
}

Running this prints:

k1:v1
k2:v2
k3:v3

Decompiled bytecode shows that keySet().iterator() creates a KeyIterator, which extends HashIterator:

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 HashIterator constructor uses a do‑while loop to locate the first non‑null entry:

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

extends HashIterator and implements Iterator, providing next() that returns the key of the next node:

final class KeyIterator extends HashIterator implements Iterator<K> {
    public final K next() { return nextNode().key; }
}

Thus, keySet traversal internally creates an iterator, which explains the apparent double iteration.

Summary

Using keySet for traversal internally invokes the iterator() method.

The iterator() method creates a KeyIterator object. KeyIterator extends HashIterator.

The HashIterator constructor searches for the first non‑empty entry via a loop.

JavaHashMapCollectionsIteratorkeySetentrySet
Architect's Tech Stack
Written by

Architect's Tech Stack

Java backend, microservices, distributed systems, containerized programming, and more.

0 followers
Reader feedback

How this landed with the community

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.