我们应该使用computeIfAbsent而不是getOrPut吗?

k31*_*159 7 concurrenthashmap kotlin

ConcurrentMap.getOrPutKotlin从一开始(1.0)就有扩展功能。它与 Java 具有相同的签名computeIfAbsent并执行类似的操作,但有一些细微的差异:

  1. getOrPut可以在条目中放入空值,但computeIfAbsent不支持。

  2. getOrPut不保证默认函数只会被调用一次,而 Java 则computeIfAbsent保证这一点。

  3. 发布时getOrPut,最新的 Java 版本是 Java 8。在 Java 8 中,computeIfAbsent即使值已经存在,也始终锁定条目。因此,Kotlin 可能具有更好的性能,因为它在不需要时不会锁定。

然而,在最新版本的 Java 中(我刚刚检查了 17),第 3 点中提到的锁定开销不再存在。所以 KotlingetOrPut不再有这个优点,但它有第 2 点的缺点。现在在什么情况下我们应该继续使用getOrPut(假设我们不想在映射中放入 null)或者现在应该将其视为“遗留” ?

Pan*_*kos 3

您已经指出了这两种方法的一些非常有趣的事实。

请考虑另外一个,这将是使用的一个理由getOrPut

  1. ComputeIfAbsent保证原子性。这意味着该方法可以并且将会在计算期间阻塞其他线程以确保原子性。

来自文档

如果指定的键尚未与值关联,则尝试使用给定的映射函数计算其值并将其输入到此映射中,除非为 null。整个方法调用是原子执行的,因此每个键最多应用该函数一次。当计算正在进行时,其他线程对此映射的某些尝试更新操作可能会被阻止,因此计算应该简短,并且不得尝试更新此映射的任何其他映射。

getOrPut不保证原子性。

来自文档

请注意,如果同时修改映射,则不能保证该操作是原子的。

这意味着在原子性对您来说并不重要的用例场景中,getOrPutcomputeIfAbsent.