Fastest & Safest HashMap Traversal: Compare Java 8 Streams, Lambdas, and Iterators
This article examines the four major HashMap traversal techniques—Iterator, for‑each loops, Lambda expressions, and Streams API—detailing seven concrete implementations, benchmarking their performance with JMH, analyzing generated bytecode, and evaluating safety when modifying collections during iteration, ultimately recommending the most efficient and secure approaches.
With the release of JDK 1.8 Streams API, HashMap now has more traversal options, but choosing the right one can be confusing.
The article first introduces HashMap traversal methods, then analyzes their performance, principles, and safety.
HashMap Traversal
HashMap traversal can be divided into four high‑level categories:
Iterator (Iterator) traversal
For‑Each traversal
Lambda expression traversal (JDK 1.8+)
Streams API traversal (JDK 1.8+)
Each category has specific implementations, resulting in seven concrete ways:
Iterator EntrySet
Iterator KeySet
For‑Each EntrySet
For‑Each KeySet
Lambda expression
Streams API single‑thread
Streams API multi‑thread
1. Iterator EntrySet
public class HashMapTest {
public static void main(String[] args) {
// create and populate HashMap
Map<Integer, String> map = new HashMap();
map.put(1, "Java");
map.put(2, "JDK");
map.put(3, "Spring Framework");
map.put(4, "MyBatis framework");
map.put(5, "Java中文社群");
// traversal
Iterator<Map.Entry<Integer, String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<Integer, String> entry = iterator.next();
System.out.print(entry.getKey());
System.out.print(entry.getValue());
}
}
}1JavaJDK3Spring Framework4MyBatis framework5Java中文社群
2. Iterator KeySet
public class HashMapTest {
public static void main(String[] args) {
// create and populate HashMap
Map<Integer, String> map = new HashMap();
map.put(1, "Java");
map.put(2, "JDK");
map.put(3, "Spring Framework");
map.put(4, "MyBatis framework");
map.put(5, "Java中文社群");
// traversal
Iterator<Integer> iterator = map.keySet().iterator();
while (iterator.hasNext()) {
Integer key = iterator.next();
System.out.print(key);
System.out.print(map.get(key));
}
}
}1Java2JDK3Spring Framework4MyBatis framework5Java中文社群
3. For‑Each EntrySet
public class HashMapTest {
public static void main(String[] args) {
// create and populate HashMap
Map<Integer, String> map = new HashMap();
map.put(1, "Java");
map.put(2, "JDK");
map.put(3, "Spring Framework");
map.put(4, "MyBatis framework");
map.put(5, "Java中文社群");
// traversal
for (Map.Entry<Integer, String> entry : map.entrySet()) {
System.out.print(entry.getKey());
System.out.print(entry.getValue());
}
}
}1Java2JDK3Spring Framework4MyBatis framework5Java中文社群
4. For‑Each KeySet
public class HashMapTest {
public static void main(String[] args) {
// create and populate HashMap
Map<Integer, String> map = new HashMap();
map.put(1, "Java");
map.put(2, "JDK");
map.put(3, "Spring Framework");
map.put(4, "MyBatis framework");
map.put(5, "Java中文社群");
// traversal
for (Integer key : map.keySet()) {
System.out.print(key);
System.out.print(map.get(key));
}
}
}1Java2JDK3Spring Framework4MyBatis framework5Java中文社群
5. Lambda
public class HashMapTest {
public static void main(String[] args) {
// create and populate HashMap
Map<Integer, String> map = new HashMap();
map.put(1, "Java");
map.put(2, "JDK");
map.put(3, "Spring Framework");
map.put(4, "MyBatis framework");
map.put(5, "Java中文社群");
// traversal
map.forEach((key, value) -> {
System.out.print(key);
System.out.print(value);
});
}
}1Java2JDK3Spring Framework4MyBatis framework5Java中文社群
6. Streams API Single‑Thread
public class HashMapTest {
public static void main(String[] args) {
// create and populate HashMap
Map<Integer, String> map = new HashMap();
map.put(1, "Java");
map.put(2, "JDK");
map.put(3, "Spring Framework");
map.put(4, "MyBatis framework");
map.put(5, "Java中文社群");
// traversal
map.entrySet().stream().forEach((entry) -> {
System.out.print(entry.getKey());
System.out.print(entry.getValue());
});
}
}1Java2JDK3Spring Framework4MyBatis framework5Java中文社群
7. Streams API Multi‑Thread
public class HashMapTest {
public static void main(String[] args) {
// create and populate HashMap
Map<Integer, String> map = new HashMap();
map.put(1, "Java");
map.put(2, "JDK");
map.put(3, "Spring Framework");
map.put(4, "MyBatis framework");
map.put(5, "Java中文社群");
// traversal
map.entrySet().parallelStream().forEach((entry) -> {
System.out.print(entry.getKey());
System.out.print(entry.getValue());
});
}
}4MyBatis framework5Java中文社群1Java2JDK3Spring Framework
Performance Test
The JMH (Java Microbenchmark Harness) framework is used to benchmark the seven traversal methods. The required dependency is added to pom.xml and the benchmark class defines methods annotated with @Benchmark for each traversal.
... (benchmark code omitted for brevity) ...The benchmark results (shown in the image below) indicate that, except for the parallelStream version, all other methods have almost identical average execution times.
Score represents the average execution time; the ± symbol shows the error margin. The parallelStream version shows a much higher throughput, while the other methods differ negligibly in performance.
Note: Results are based on JDK 1.8 / Mac mini (2018) / IDEA 2020.1
Performance Principle Analysis
By decompiling the compiled bytecode with javac and viewing it in IDEA, we see that Iterator‑based and for‑each loops over EntrySet generate identical bytecode, as do Iterator‑based and for‑each loops over KeySet. The only noticeable difference is that KeySet creates a temporary Integer variable during iteration.
Therefore, the performance gap between EntrySet and KeySet is minimal, contrary to some online claims.
Safety Test
Four traversal categories—Iterator, for‑each, Lambda, and Stream—are tested for safe removal of elements during iteration.
1. Iterator
Iterator<Map.Entry<Integer, String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<Integer, String> entry = iterator.next();
if (entry.getKey() == 1) {
System.out.println("del:" + entry.getKey());
iterator.remove(); // safe
} else {
System.out.println("show:" + entry.getKey());
}
}show:0 del:1 show:2
Result: removal via iterator is safe.
2. For‑Each Loop
for (Map.Entry<Integer, String> entry : map.entrySet()) {
if (entry.getKey() == 1) {
System.out.println("del:" + entry.getKey());
map.remove(entry.getKey()); // unsafe
} else {
System.out.println("show:" + entry.getKey());
}
}Result: removal inside a for‑each loop is unsafe.
3. Lambda
map.forEach((key, value) -> {
if (key == 1) {
System.out.println("del:" + key);
map.remove(key); // unsafe
} else {
System.out.println("show:" + key);
}
});Result: removal inside a Lambda is unsafe. The correct approach is to use map.keySet().removeIf(key -> key == 1) before iteration.
4. Stream
map.entrySet().stream().forEach((entry) -> {
if (entry.getKey() == 1) {
System.out.println("del:" + entry.getKey());
map.remove(entry.getKey()); // unsafe
} else {
System.out.println("show:" + entry.getKey());
}
});Result: removal inside a Stream forEach is unsafe. The safe way is to filter out unwanted entries first:
map.entrySet().stream()
.filter(e -> e.getKey() != 1)
.forEach(e -> System.out.println("show:" + e.getKey()));Summary
All four traversal categories were evaluated for performance and safety. Apart from the parallel Stream version, performance differences are negligible, while Lambda and Stream offer the most concise syntax. For safe removal during iteration, use iterator.remove(), removeIf, or filter before looping.
Choosing a traversal method should consider performance, safety, JDK version, readability, and elegance.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
