Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't Java have a putIfAbsent(key, supplier) method in Map?

Tags:

I just recently found myself wanting a version of putIfAbsent(...) in java.util.Map that you can supply some kind of factory method to, to instantiate an Object if it's not already present. This would simplify a lot of code.

Here is my modified interface:

import java.util.Map;
import java.util.function.Supplier;

/**
 * Extension of the Map Interface for a different approach on having putIfAbsent
 * 
 * @author Martin Braun
 */
public interface SupplierMap<K, V> extends Map<K, V> {

    public default V putIfAbsent(K key, Supplier<V> supplier) {
        V value = this.get(key);
        if(value == null) {
            this.put(key, value = supplier.get());
        }
        return value;
    }

}

Now my question: Is there another (easier) way of doing this or have I just overlooked something in the Java API?

like image 531
Martin Braun Avatar asked Nov 25 '14 12:11

Martin Braun


People also ask

What is putIfAbsent in map?

The Java HashMap putIfAbsent() method inserts the specified key/value mapping to the hashmap if the specified key is already not present in the hashmap. The syntax of the putIfAbsent() method is: hashmap.putIfAbsent(K key, V value) Here, hashmap is an object of the HashMap class.

What is difference between computeIfAbsent and putIfAbsent?

putIfAbsent adds an element with the specified Value whereas computeIfAbsent adds an element with the value computed using the Key.

What is put if absent?

The putIfAbsent method adds the key-value pair to the map if the key is not present in the map. If the key is already present, then it skips the operation.

What is MAP GET method in Java?

The get() method of Map interface in Java is used to retrieve or fetch the value mapped by a particular key mentioned in the parameter. It returns NULL when the map contains no such mapping for the key.


Video Answer


2 Answers

Isn't computeIfAbsent what you want?

If the specified key is not already associated with a value (or is mapped to null), attempts to compute its value using the given mapping function and enters it into this map unless null.

Implementation is something like:

if (map.get(key) == null) {
    V newValue = mappingFunction.apply(key);
    if (newValue != null) {
         map.put(key, newValue);
    }
}

So it's not exactly the Supplier<V> signature you've posted but close to that. Having key as argument in the mapping function definitely makes sense.

like image 177
lexicore Avatar answered Sep 23 '22 04:09

lexicore


computeIfAbsent is not a 1:1 replacement for putIfAbsent because constraints for the returned value do not match. While putIfAbsent returns null when a new entry is created, computeIfAbsent always return the assigned value.

A default implementation as suggested above with a call to get and then put works, but it requires two lookups in the map, which destroys the idea of a performant in-situ replacement.

like image 26
Aison Avatar answered Sep 23 '22 04:09

Aison