The java.util.Map interface represents a mapping between keys and their values. A maps cannot contain duplicate keys; and each key can maps to at most one value.
Since Maps is an interface, then you need to instantiate a concrete implementation of that interface in order to use it; there are several Maps implementations, and mostly used are the java.util.HashMap and java.util.TreeMap
Iterating Map Entries Efficiently
This section provides code and benchmarks for ten unique example implementations which iterate over the entries of a Maps 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.
Related Article: Iterating through the contents of a Map
- Implementation using Iterator with Map.Entry
Iterator> it = map.entrySet().iterator(); while (it.hasNext()) { Map.Entry pair = it.next(); sum += pair.getKey() + pair.getValue(); }
- Implementation using for with Map.Entry
for (Map.Entry pair : map.entrySet()) { sum += pair.getKey() + pair.getValue(); }
- Implementation using Map.forEach (Java 8+)
map.forEach((k, v) -> sum[0] += k + v);
- Implementation using Map.keySet with for
for (Integer key : map.keySet()) { sum += key + map.get(key); }
- Implementation using Map.keySet with Iterator
Iterator it = map.keySet().iterator(); while (it.hasNext()) { Integer key = it.next(); sum += key + map.get(key); }
- Implementation using for with Iterator and Map.Entry
for (Iterator> entries = map.entrySet().iterator(); entries.hasNext(); ) {
Map.Entry entry = entries.next();
sum += entry.getKey() + entry.getValue();
}
- The Implementation using Stream.forEach (Java 8+)
map.entrySet().stream().forEach(e -> sum += e.getKey() + e.getValue());
- Stream.forEach with Stream.parallel (Java 8+) by using Implementation
map.entrySet() .stream() .parallel() .forEach(e -> sum += e.getKey() + e.getValue());
- Implementation using IterableMap from Apache Collections
MapIterator mit = iterableMap.mapIterator(); while (mit.hasNext()) { sum += mit.next() + it.getValue(); }
- Implementation using MutableMap from Eclipse Collection
mutableMap.forEachKeyValue((key, value) -> { sum += key + value; });
Performance Tests
Test Environment: Windows 8.1 64-bit, Intel i7-4790 3.60GHz, 16 GB
- 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 |
- A Comparison of Performance Variations Respective to Map Size
Usage of HashMap
HashMap is an implementation of the Map interface that provides a Data Structure to store data in Key-Value pairs.
- Declaring HashMap
Map myMap = new HashMap();
KeyType and ValueType must be valid types in Java, such as – String, Integer, Float or any custom class like Employee, Student etc..
For Example : Map myMap = new HashMap();
- Putting values in HashMap.
To put a value in the HashMap, we have to call put method on the HashMap object by passing the Key and the Value as parameters.
myMap.put("key1", 1);
myMap.put("key2", 2);
If you call the put method with the Key that already exists in the Map, the method will override its value and return the old value.
- Getting values from HashMap.
For getting the value from a HashMap you have to call the get method, by passing the Key as a parameter.
myMap.get("key1"); //return 1 (class Integer)
If you pass a key that does not exists in the HashMap, this method will return null.
- Check whether the Key is in the Map or not.
myMap.containsKey(varKey);
- Check whether the Value is in the Map or not.
myMap.containsValue(varValue);
The above methods will return a boolean value true or false if key, value exists in the Map or not.
Using Default Methods of Map from Java 8
Examples of using Default Methods introduced in Java 8 in Map interface
- Using getOrDefault
Returns the value mapped to the key, or if the key is not present, returns the default value
Map map = new HashMap<>(); map.put(1, "First element"); map.get(1); // => First element map.get(2); // => null map.getOrDefault(2, "Default element"); // => Default element
- Using forEach
Allows to perform the operation specified in the ‘action’ on each Map Entry
Map map = new HashMap();
map.put(1, "one");
map.put(2, "two");
map.put(3, "three");
map.forEach((key, value) -> System.out.println("Key: "+key+ " :: Value: "+value));
// Key: 1 :: Value: one
// Key: 2 :: Value: two
// Key: 3 :: Value: three
- Using replaceAll
Will replace with new-value only if key is present
Map map = new HashMap();
map.put("john", 20);
map.put("paul", 30);
map.put("peter", 40);
map.replaceAll((key,value)->value+10); //{john=30, paul=40, peter=50}
- Using putIfAbsent
Key-Value pair is added to the map, if the key is not present or mapped to null
Map map = new HashMap();
map.put("john", 20);
map.put("paul", 30);
map.put("peter", 40);
map.putIfAbsent("kelly", 50); //{john=20, paul=30, peter=40, kelly=50}
- Using remove
Removes the key only if its associated with the given value
Map map = new HashMap();
map.put("john", 20);
map.put("paul", 30);
map.put("peter", 40);
map.remove("peter",40); //{john=30, paul=40}
- Using replace
If the key is present then the value is replaced by new-value. If the key is not present, does nothing.
Map map = new HashMap();
map.put("john", 20);
map.put("paul", 30);
map.put("peter", 40);
map.replace("peter",50); //{john=20, paul=30, peter=50}
map.replace("jack",60); //{john=20, paul=30, peter=50}
- Using computeIfAbsent
This method adds an entry in the Map. the key is specified in the function and the value is the result of the application of the mapping function
Map map = new HashMap();
map.put("john", 20);
map.put("paul", 30);
map.put("peter", 40);
map.computeIfAbsent("kelly", k->map.get("john")+10); //{john=20, paul=30, peter=40, kelly=30}
map.computeIfAbsent("peter", k->map.get("john")+10); //{john=20, paul=30, peter=40, kelly=30}
//peter already present
- Using computeIfPresent
This method adds an entry or modifies an existing entry in the Map. Does nothing if an entry with that key is not present
Map map = new HashMap();
map.put("john", 20);
map.put("paul", 30);
map.put("peter", 40);
map.computeIfPresent("kelly", (k,v)->v+10); //{john=20, paul=30, peter=40} //kelly not present
map.computeIfPresent("peter", (k,v)->v+10); //{john=20, paul=30, peter=50} // peter present, so
increase the value
- Using compute
This method replaces the value of a key by the newly computed value
Map map = new HashMap();
map.put("john", 20);
map.put("paul", 30);
map.put("peter", 40);
map.compute("peter", (k,v)->v+50); //{john=20, paul=30, peter=90} //Increase the value
- Using merge
Adds the key-value pair to the map, if key is not present or value for the key is null Replaces the value with the newly computed value, if the key is present Key is removed from the map , if new value computed is null
Map map = new HashMap();
map.put("john", 20);
map.put("paul", 30);
map.put("peter", 40);
//Adds the key-value pair to the map, if key is not present or value for the key is null
map.merge("kelly", 50 , (k,v)->map.get("john")+10); // {john=20, paul=30, peter=40, kelly=50}
//Replaces the value with the newly computed value, if the key is present
map.merge("peter", 50 , (k,v)->map.get("john")+10); //{john=20, paul=30, peter=30, kelly=50}
//Key is removed from the map , if new value computed is null
map.merge("peter", 30 , (k,v)->map.get("nancy")); //{john=20, paul=30, kelly=50}