How do I efficiently iterate over each entry in a Java Map?
Map<String, String> map = ...for (Map.Entry<String, String> entry : map.entrySet()) { System.out.println(entry.getKey() + "/" + entry.getValue());}
On Java 10+:
for (var entry : map.entrySet()) { System.out.println(entry.getKey() + "/" + entry.getValue());}
To summarize the other answers and combine them with what I know, I found 10 main ways to do this (see below). Also, I wrote some performance tests (see results below). For example, if we want to find the sum of all of the keys and values of a map, we can write:
Using iterator and Map.Entry
long i = 0;Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();while (it.hasNext()) { Map.Entry<Integer, Integer> pair = it.next(); i += pair.getKey() + pair.getValue();}
Using foreach and Map.Entry
long i = 0;for (Map.Entry<Integer, Integer> pair : map.entrySet()) { i += pair.getKey() + pair.getValue();}
Using forEach from Java 8
final long[] i = {0};map.forEach((k, v) -> i[0] += k + v);
Using keySet and foreach
long i = 0;for (Integer key : map.keySet()) { i += key + map.get(key);}
Using keySet and iterator
long i = 0;Iterator<Integer> itr2 = map.keySet().iterator();while (itr2.hasNext()) { Integer key = itr2.next(); i += key + map.get(key);}
Using for and Map.Entry
long i = 0;for (Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator(); entries.hasNext(); ) { Map.Entry<Integer, Integer> entry = entries.next(); i += entry.getKey() + entry.getValue();}
Using the Java 8 Stream API
final long[] i = {0};map.entrySet().stream().forEach(e -> i[0] += e.getKey() + e.getValue());
Using the Java 8 Stream API parallel
final long[] i = {0};map.entrySet().stream().parallel().forEach(e -> i[0] += e.getKey() + e.getValue());
Using IterableMap of
Apache Collections
long i = 0;MapIterator<Integer, Integer> it = iterableMap.mapIterator();while (it.hasNext()) { i += it.next() + it.getValue();}
Using MutableMap of Eclipse (CS) collections
final long[] i = {0};mutableMap.forEachKeyValue((key, value) -> { i[0] += key + value;});
Perfomance tests (mode = AverageTime, system = Windows 8.1 64-bit, Intel i7-4790 3.60 GHz, 16 GB)
For a small map (100 elements), score 0.308 is the best
Benchmark Mode Cnt Score Error Unitstest3_UsingForEachAndJava8 avgt 10 0.308 ± 0.021 µs/optest10_UsingEclipseMap avgt 10 0.309 ± 0.009 µs/optest1_UsingWhileAndMapEntry avgt 10 0.380 ± 0.014 µs/optest6_UsingForAndIterator avgt 10 0.387 ± 0.016 µs/optest2_UsingForEachAndMapEntry avgt 10 0.391 ± 0.023 µs/optest7_UsingJava8StreamApi avgt 10 0.510 ± 0.014 µs/optest9_UsingApacheIterableMap avgt 10 0.524 ± 0.008 µs/optest4_UsingKeySetAndForEach avgt 10 0.816 ± 0.026 µs/optest5_UsingKeySetAndIterator avgt 10 0.863 ± 0.025 µs/optest8_UsingJava8StreamApiParallel avgt 10 5.552 ± 0.185 µs/op
For a map with 10000 elements, score 37.606 is the best
Benchmark Mode Cnt Score Error Unitstest10_UsingEclipseMap avgt 10 37.606 ± 0.790 µs/optest3_UsingForEachAndJava8 avgt 10 50.368 ± 0.887 µs/optest6_UsingForAndIterator avgt 10 50.332 ± 0.507 µs/optest2_UsingForEachAndMapEntry avgt 10 51.406 ± 1.032 µs/optest1_UsingWhileAndMapEntry avgt 10 52.538 ± 2.431 µs/optest7_UsingJava8StreamApi avgt 10 54.464 ± 0.712 µs/optest4_UsingKeySetAndForEach avgt 10 79.016 ± 25.345 µs/optest5_UsingKeySetAndIterator avgt 10 91.105 ± 10.220 µs/optest8_UsingJava8StreamApiParallel avgt 10 112.511 ± 0.365 µs/optest9_UsingApacheIterableMap avgt 10 125.714 ± 1.935 µs/op
For a map with 100000 elements, score 1184.767 is the best
Benchmark Mode Cnt Score Error Unitstest1_UsingWhileAndMapEntry avgt 10 1184.767 ± 332.968 µs/optest10_UsingEclipseMap avgt 10 1191.735 ± 304.273 µs/optest2_UsingForEachAndMapEntry avgt 10 1205.815 ± 366.043 µs/optest6_UsingForAndIterator avgt 10 1206.873 ± 367.272 µs/optest8_UsingJava8StreamApiParallel avgt 10 1485.895 ± 233.143 µs/optest5_UsingKeySetAndIterator avgt 10 1540.281 ± 357.497 µs/optest4_UsingKeySetAndForEach avgt 10 1593.342 ± 294.417 µs/optest3_UsingForEachAndJava8 avgt 10 1666.296 ± 126.443 µs/optest7_UsingJava8StreamApi avgt 10 1706.676 ± 436.867 µs/optest9_UsingApacheIterableMap avgt 10 3289.866 ± 1445.564 µs/op
Graphs (performance tests depending on map size)
Table (perfomance tests depending on map size)
100 600 1100 1600 2100test10 0.333 1.631 2.752 5.937 8.024test3 0.309 1.971 4.147 8.147 10.473test6 0.372 2.190 4.470 8.322 10.531test1 0.405 2.237 4.616 8.645 10.707test2 0.376 2.267 4.809 8.403 10.910test7 0.473 2.448 5.668 9.790 12.125test9 0.565 2.830 5.952 13.220 16.965test4 0.808 5.012 8.813 13.939 17.407test5 0.810 5.104 8.533 14.064 17.422test8 5.173 12.499 17.351 24.671 30.403
All tests are on GitHub.
In Java 8 you can do it clean and fast using the new lambdas features:
Map<String,String> map = new HashMap<>(); map.put("SomeKey", "SomeValue"); map.forEach( (k,v) -> [do something with key and value] ); // such as map.forEach( (k,v) -> System.out.println("Key: " + k + ": Value: " + v));
The type of k
and v
will be inferred by the compiler and there is no need to use Map.Entry
anymore.
Easy-peasy!