在Java 8 Map中,putIfAbsent和computeIfAbsent有什么区别?

2022-08-31 09:07:26

阅读一篇有趣的文章,这些家伙声称这两个函数之间的区别是:

如果 Map 中尚不存在指定的 Key,则这两个函数都希望添加元素。

putIfAbsent 添加一个具有指定值的元素,而 computeIfAbsent 添加一个具有使用 Key 计算的值的元素。http://www.buggybread.com/2014/10/java-8-difference-between-map.html

我们已经看到 putIfAbsent 消除了必须定义 if 语句的命令性方式,但是如果获取 Java 文章真的损害了我们的性能呢?

为了优化这一点,我们不想获取文章,直到我们真正确定我们需要它们 - 这意味着我们需要在获取文章之前知道密钥是否不存在。http://www.deadcoderising.com/2017-02-14-java-8-declarative-ways-of-modifying-a-map-using-compute-merge-and-replace/

我还没有准备好了解有什么区别,你能详细阐述这两个功能吗?


答案 1

区别 #1

computeIfAbsent 采用映射函数,如果缺少键,则调用该函数来获取值。

putIfAbsent 直接获取值。

如果获取该值的成本很高,则在密钥已存在的情况下浪费该值。putIfAbsent

一个常见的“昂贵”值是例如 ,当您创建时,当键已经存在时创建新列表(然后丢弃新列表)会产生不必要的垃圾。new ArrayList<>()Map<K, List<V>>


差异 #2

computeIfAbsent 返回“与指定键关联的当前(现有或已计算)值,如果计算值为 null,则返回 null”。

putIfAbsent 返回“与指定键关联的上一个值,如果没有键的映射,则返回 null”。

因此,如果密钥已存在,则它们返回相同的内容,但如果缺少该密钥,则返回计算值,同时返回 null。computeIfAbsentputIfAbsent


区别 #3

这两种方法都将“absent”定义为键缺失或现有值为 null,但是:

如果密钥不存在,computeIfAbsent 将不会放置空值。

putIfAbsent 将在键不存在时放置该值,即使该值为 null。

对于将来对计算IfAbsent,putIfAbsentget调用的调用没有区别,但是它确实对getOrDefaultcontainsKey等调用有所作为。


答案 2

假设您有一个 .Map<String,ValueClass>

map.putIfAbsent("key", new ValueClass());

无论如何都会创建一个实例,即使“key”键已经在 .这只会创建一个不必要的实例。ValueClassMap

另一方面

map.computeIfAbsent("key", k -> new ValueClass());

仅当“key”键尚未在 (或映射到值) 中时,才会创建实例。ValueClassMapnull

因此效率更高。computeIfAbsent

putIfAbsent等效于:

ValueClass value = new ValueClass();
if (map.get("key") == null) {
    map.put("key",value);
}

而等效于:computeIfAbsent

if (map.get("key") == null) {
    map.put("key",new ValueClass());
}

这两种方法之间的另一个小区别是不会为缺少的键放置值。 将。computeIfAbsentnullputIfAbsent


推荐