In Java 8, the Map
interface has been updated to include several new, convenient methods. Some of the important changes are outlined below:
computeIfAbsent
is particularly useful when implementing the caching pattern. For example, previously, you would do this:
private final Map<String, Data> map = new HashMap<>(); public Data getData(final String key) { Data data = map.get(key); // look in cache if (data == null) { // data is not in cache data = computeData(key); // perform an (expensive) operation map.put(key, data); // put data in cache } return data; // return data }
You can now write this method more concisely as follows:
public Data getData(final String key) { return map.computeIfAbsent(key, this::computeData); }
You can also use computeIfAbsent
when implementing a "multi-map" (Map<K, Collection<V>>
):
map.computeIfAbsent(key, k -> new ArrayList<V>()).add(v);2. putIfAbsent
putIfAbsent
puts a value in the map, if the key is not already present. For example, instead of this:
final Map<String, String> map = new HashMap<>(); final String v = map.get(k); if (v == null) { map.put(k, newValue); }
you can write:
final Map<String, String> map = new HashMap<>(); map.putIfAbsent(k, newValue);3. getOrDefault
getOrDefault
returns a default value, if a specified key is not found in the map. Previously, you would do this:
final Map<String, String> map = new HashMap<>(); return map.containsKey(key) ? map.get(key) : "foo";
Now you can write:
final Map<String, String> map = new HashMap<>(); return map.getOrDefault(key, "foo");4. Performance
The implementation of HashMap
has been updated so that when buckets become too big (see the "TREEIFY_THRESHOLD" setting) they are transformed from lists (with O(n) retrieval) into trees (with faster O(log(n)) retrieval). This improves performance when hashCode()
methods return values that are poorly distributed, or when many keys share the same hashCode
, so long as they are also Comparable
.