Iterating Map Entries Effciently


Maps

The java.util.Map interface represents a mapping between keys and their values. A map cannot contain duplicate keys; and each key can map to at most one value.

Since Map is an interface, then you need to instantiate a concrete implementation of that interface in order to use it; there are several Map implementations, and mostly used are the java.util.HashMap and java.util.TreeMap


Iterating Map Entries Effciently

This section provides code and benchmarks for ten unique example implementations which iterate over the entries of a Map and generate the sum of the Integer values. All of the examples have an algorithmic complexity of Θ(n), however, the benchmarks are still useful for providing insight on which implementations are more efficient in a "real world" environment.

1.Implementation using Iterator with Map.Entry

 Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
 while (it.hasNext()) {
 Map.Entry<Integer, Integer> pair = it.next();
 sum += pair.getKey() + pair.getValue();
 }
 
2. Implementation using for with Map.Entry

 for (Map.Entry<Integer, Integer> pair : map.entrySet()) {
 sum += pair.getKey() + pair.getValue();
 }
 
3. Implementation using Map.forEach (Java 8+)

 map.forEach((k, v) -> sum[0] += k + v);
 
4. Implementation using Map.keySet with for

 for (Integer key : map.keySet()) {
 sum += key + map.get(key);
 }
 
5. Implementation using Map.keySet with Iterator

 Iterator<Integer> it = map.keySet().iterator();
 while (it.hasNext()) {
 Integer key = it.next();
 sum += key + map.get(key);
 }
 
6. Implementation using for with Iterator and Map.Entry

 for (Iterator<Map.Entry<Integer, Integer>> entries =
 map.entrySet().iterator(); entries.hasNext(); ) {
 Map.Entry<Integer, Integer> entry = entries.next();
 sum += entry.getKey() + entry.getValue();
 }
 
7. Implementation using Stream.forEach (Java 8+)

 map.entrySet().stream().forEach(e -> sum += e.getKey() + e.getValue());
 
8. Implementation using Stream.forEach with Stream.parallel (Java 8+)

 map.entrySet()
 .stream()
 .parallel()
 .forEach(e -> sum += e.getKey() + e.getValue());
 
9. Implementation using IterableMap from Apache Collections

 MapIterator<Integer, Integer> mit = iterableMap.mapIterator();
 while (mit.hasNext()) {
 sum += mit.next() + it.getValue();
 }
 
10. Implementation using MutableMap from Eclipse Collections

 mutableMap.forEachKeyValue((key, value) -> {
 sum += key + value;
 });
 

Performance Tests

Average Performance of 10 Trials (100 elements) Best: 308±21 ns/op

Benchmark Score Error Units
test3_UsingForEachAndJava8 308 ± 21 ns/op
test10_UsingEclipseMutableMap 309 ± 9 ns/op
test1_UsingWhileAndMapEntry 380 ± 14 ns/op
test6_UsingForAndIterator 387 ± 16 ns/op
test2_UsingForEachAndMapEntry 391 ± 23 ns/op
test7_UsingJava8StreamAPI 510 ± 14 ns/op
test9_UsingApacheIterableMap 524 ± 8 ns/op
test4_UsingKeySetAndForEach 816 ± 26 ns/op
test5_UsingKeySetAndIterator 863 ± 25 ns/op
test8_UsingJava8StreamAPIParallel 5552 ± 185 ns/op

Average Performance of 10 Trials (10000 elements) Best: 37.606±0.790 μs/op

Benchmark Score Error Units
test10_UsingEclipseMutableMap 37606 ± 790 ns/op
test3_UsingForEachAndJava8 50368 ± 887 ns/op
test6_UsingForAndIterator 50332 ± 507 ns/op
test2_UsingForEachAndMapEntry 51406 ± 1032 ns/op
test1_UsingWhileAndMapEntry 52538 ± 2431 ns/op
test7_UsingJava8StreamAPI 54464 ± 712 ns/op
test4_UsingKeySetAndForEach 79016 ± 25345 ns/op
test5_UsingKeySetAndIterator 91105 ± 10220 ns/op
test8_UsingJava8StreamAPIParallel 112511 ± 365 ns/op
test9_UsingApacheIterableMap 125714 ± 1935 ns/op

Average Performance of 10 Trials (100000 elements) Best: 1184.767±332.968 μs/op

Benchmark Score Error Units
test1_UsingWhileAndMapEntry 1184.767 ± 332.968 μs/op
test10_UsingEclipseMutableMap 1191.735 ± 304.273 μs/op
test2_UsingForEachAndMapEntry 1205.815 ± 366.043 μs/op
test6_UsingForAndIterator 1206.873 ± 367.272 μs/op
test8_UsingJava8StreamAPIParallel 1485.895 ± 233.143 μs/op
test5_UsingKeySetAndIterator 1540.281 ± 357.497 μs/op
test4_UsingKeySetAndForEach 1593.342 ± 294.417 μs/op
test3_UsingForEachAndJava8 1666.296 ± 126.443 μs/op
test7_UsingJava8StreamAPI 1706.676 ± 436.867 μs/op
test9_UsingApacheIterableMap 3289.866 ± 1445.564 μs/op

Basic Programs