为什么Java在Map中没有putIfAbsent(key,supplier)方法?

2022-09-02 10:13:14

我最近发现自己想要一个java.util.Map中的putIfAbsent(...)版本,你可以提供某种工厂方法,如果对象尚不存在,则可以实例化它。这将简化大量代码。

这是我修改后的界面:

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

}

现在我的问题是:有没有另一种(更简单)的方法可以做到这一点,或者我只是忽略了Java API中的某些东西?


答案 1

computeIfAbsent 不是你想要的嗎?

如果指定的键尚未与值关联(或映射到 null),则尝试使用给定的映射函数计算其值,并将其输入到此映射中,除非为 null。

实现类似于:

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

因此,它不完全是您发布的签名,但接近于此。在映射函数中使用 key 作为参数绝对有意义。Supplier<V>


答案 2

computeIfAbsent 不是 putIfAbsent 的 1:1 替代,因为返回值的约束不匹配。虽然 putIfAbsent 在创建新条目时返回 null但 computeIfAbsent 始终返回分配的值。

如上所述,使用调用来获取然后放置工作的默认实现,但它需要在映射中进行两次查找,这破坏了高性能原位替换的想法。