Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8: Get default value from HashMap and update underlying map [duplicate]

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?

like image 947
Stephen Asherson Avatar asked Dec 29 '16 08:12

Stephen Asherson


People also ask

What is the default value of HashMap in Java?

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.

How does HashMap increase value by 1?

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);

How do I change the value of a HashMap in Java?

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.


2 Answers

The computeIfAbsent method is designed for exactly this purpose:

List<Integer> value = 
    someIntegerListLookup.computeIfAbsent("a", x -> new ArrayList<>());
like image 145
Mureinik Avatar answered Oct 19 '22 18:10

Mureinik


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<>());
like image 32
Eran Avatar answered Oct 19 '22 16:10

Eran