I'm looking for the best way (readability and efficiency) of providing a default value for a HashMap
get operation but to also have the underlying map updated with that default value if a value is not already present.
I understand there are 3rd party libraries out there, but I'd prefer to stick with standard Java. Here are some different ways I've thought of:
Old school
Map<String, List<Integer>> someIntegerListLookup = new HashMap<>();
String key = "key";
...
List<Integer> integerList = someIntegerListLookup.get(key);
if (integerList == null) {
integerList = new ArrayList<>();
someIntegerListLookup.put(key, integerList);
}
Java 8 Map methods
// getOrDefault
List<Integer> integerList = someIntegerListLookup.getOrDefault(key, new ArrayList<>());
someIntegerListLookup.put(key, integerList);
// putIfAbsent
someIntegerListLookup.putIfAbsent(key, new ArrayList<>());
List<Integer> integerList = someIntegerListLookup.get(key);
Using Java 8 Optionals
List<Integer> integerList =
Optional.ofNullable(someIntegerListLookup.putIfAbsent(key, new ArrayList<>()))
.orElse(someIntegerListLookup.get(key));
Not a fan of this approach from a readability point of view.
Using an 'or else' supplier:
List<Integer> integerList = Optional.ofNullable(someIntegerListLookup.get(key))
.orElseGet(() -> {
// Only runs if the map contains no value for the key
List<Integer> defaultIntegersList = new ArrayList<>();
someIntegerListLookup.put(key, defaultIntegersList);
return defaultIntegersList;
});
Right now I'm leaning towards the above solution being the best option. Are there other (better) solutions out there for this that I haven't thought of or come across?
Constructs a new HashMap with the same mappings as the specified Map. The HashMap is created with default load factor (0.75) and an initial capacity sufficient to hold the mappings in the specified Map.
Map<String, Integer> map = new HashMap<>(); String key = "a random key"; int count = map. getOrDefault(key, 0); // ensure count will be one of 0,1,2,3,... map. put(key, count + 1);
hashmap. put(key, hashmap. get(key) + 1); The method put will replace the value of an existing key and will create it if doesn't exist.
The computeIfAbsent
method is designed for exactly this purpose:
List<Integer> value =
someIntegerListLookup.computeIfAbsent("a", x -> new ArrayList<>());
You don't want to create a new ArrayList
unnecessarily if the key is present.
Therefore use :
List<Integer> integerList = someIntegerListLookup.computeIfAbsent(key, s -> new ArrayList<>());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With