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

新手上路,请多包涵

阅读一篇有趣的文章,这些人声称这两个功能之间的区别是:

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

putIfAbsent 添加一个具有指定 Value 的元素,而 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/

我还没准备好了解这两个功能有什么区别,您能详细说明一下吗?

原文由 Adelin 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.8k
2 个回答

差异 #1

computeIfAbsent 接受一个映射函数,如果键丢失,调用它来获取值。

putIfAbsent 直接取值。

如果获取该值的成本很高,那么 putIfAbsent 如果密钥已经存在,则会浪费它。

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


差异 #2

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

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

所以,如果密钥已经存在,它们返回相同的东西,但如果密钥丢失, computeIfAbsent 返回计算值,而 putIfAbsent 返回空值。


差异 #3

这两种方法都将“不存在”定义为缺少键或现有值为空,但是:

computeIfAbsent 如果密钥不存在,则不会输入空值。

putIfAbsent 如果键不存在,即使值为空,也会放置值。

It makes no difference for future calls to computeIfAbsent , putIfAbsent , and get calls, but it does make a difference to calls like getOrDefaultcontainsKey

原文由 Andreas 发布,翻译遵循 CC BY-SA 3.0 许可协议

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

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

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

另一方面

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

如果“键”键不在 Map 中(或映射到 null 值),则只会创建一个 ValueClass 实例。

因此 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());
}

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

原文由 Eran 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题