Back to Blog
Java

Java HashMap entrySet: Iterate Efficiently

java hashmap entryset: Learn how to use HashMap entrySet() to iterate over key-value pairs efficiently, with practical examples and performance considerations.

JavaHashMapentrySetIterationCollectionsPerformance
Illustration of Java HashMap entrySet iteration showing key-value pairs being accessed

java hashmap entryset requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.

The entrySet() method on a Java HashMap returns a Set view of the mappings contained in the map. It is the most direct way to access both the key and the value during iteration, and it is the foundation of many map-processing patterns. When you need to traverse a HashMap and work with each key-value pair, entrySet() is usually the right choice.

What entrySet() Returns and Why It Matters

entrySet() returns a Set<Map.Entry<K, V>>. Each Map.Entry represents a single key-value pair and exposes getKey(), getValue(), and setValue(). The returned set is backed by the map, so changes you make to the set (like removing an entry) are reflected in the original map. This live view is important for both iteration and modification.

Map<String, Integer> scores = new HashMap<>(); scores.put("Alice", 90); scores.put("Bob", 85); Set<Map.Entry<String, Integer>> entries = scores.entrySet(); for (Map.Entry<String, Integer> entry : entries) { System.out.println(entry.getKey() + ": " + entry.getValue()); }

The entrySet() method is defined in the Map interface, so it works for TreeMap, LinkedHashMap, and other map implementations. However, the iteration order depends on the specific implementation. A HashMap does not guarantee order, while a LinkedHashMap preserves insertion order.

Basic Iteration with for-each

The most common pattern is a for-each loop over the entry set. This avoids a separate lookup for each key, which would happen if you iterated over keySet() and then called get() for each key.

for (Map.Entry<String, Integer> entry : map.entrySet()) { String key = entry.getKey(); Integer value = entry.getValue(); // process key and value }

This is concise and readable. The loop variable entry is a live view of the map's internal structure. If you modify the map from another thread during iteration without proper synchronization, you may get a ConcurrentModificationException. That is a separate concern from the entrySet() API itself.

Modifying Entries During Iteration

Because each Map.Entry is backed by the map, you can update the value of an existing key without explicitly calling put() again. This is often more efficient because it avoids an extra hash lookup.

for (Map.Entry<String, Integer> entry : map.entrySet()) { if (entry.getValue() < 50) { entry.setValue(entry.getValue() + 10); } }

Removing entries during iteration is also possible using the iterator's remove() method. This is the safe way to remove while iterating; calling map.remove() directly would cause a ConcurrentModificationException.

Iterator<Map.Entry<String, Integer>> iterator = map.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String, Integer> entry = iterator.next(); if (entry.getValue() == 0) { iterator.remove(); } }

The iterator's remove() method is backed by the map and maintains the iteration's integrity.

Performance: entrySet() vs keySet() vs values()

The choice of iteration method affects runtime cost, especially for large maps. The table below summarizes the key differences.

MethodWhat you getExtra lookup per entryBest when
entrySet()Key and valueNoYou need both key and value
keySet()Keys onlyYes (via get())You only need keys, or you need to modify values with put()
values()Values onlyNoYou only need values

Iterating over keySet() and then calling get() for each key performs an additional hash lookup for every entry. For a HashMap with a good hash function, this is O(1) per lookup, but it still adds overhead. If you need both the key and the value, entrySet() avoids that extra work.

There is also a memory consideration: entrySet() returns a view, not a copy. It does not allocate a new collection. The same is true for keySet() and values(). So the performance difference is purely about the number of operations per iteration.

Common Pitfalls and Edge Cases

One common mistake is assuming that entrySet() returns a snapshot. It does not. The set is backed by the map, so structural modifications (adding or removing entries) outside of the iterator will cause a ConcurrentModificationException if they happen during iteration. This is fail-fast behavior designed to catch bugs early.

Another pitfall is using entrySet() on a null map, which will throw a NullPointerException. Always ensure the map is non-null before calling entrySet().

When you only need to update values, you might be tempted to use keySet() and call put() for each key. This works, but it performs two hash lookups per entry: one for the key in the iteration and one for the put(). Using entrySet() with setValue() is more efficient and also expresses the intent more clearly.

If the map is very large and you only need the keys, iterating over keySet() is appropriate. But if you later need the value, you will pay the extra lookup. Consider your actual data access pattern before choosing.

When to Use entrySet() Over Other Approaches

Use entrySet() when you need to read both keys and values, or when you need to modify values in place. It is the standard, idiomatic way to iterate over a map's contents. For Java 8 and later, you can also use forEach() with a lambda:

map.forEach((key, value) -> { System.out.println(key + " -> " + value); });

The forEach method internally uses entrySet() and is a more functional alternative. However, forEach does not allow you to remove entries during iteration; you would need an explicit iterator for that.

If you need to iterate and remove entries conditionally, the iterator over entrySet() is the correct approach. If you need to transform the map into another structure, entrySet() provides a natural source for stream operations:

Map<String, Integer> doubled = map.entrySet().stream() .collect(Collectors.toMap( Map.Entry::getKey, e -> e.getValue() * 2 ));

This pattern is concise and avoids the overhead of a separate get() call. The choice between entrySet() and other methods ultimately depends on whether you need both key and value, and whether you need to modify the map during iteration. In most cases, entrySet() is the safest and most efficient default.

java hashmap entryset: Practical Usage and Code Examples | RYUSLOG DEV