简体   繁体   English

为什么 ConcurrentHashMap.computeIfAbsent() 为已经存在的键增加计数器?

[英]Why does ConcurrentHashMap.computeIfAbsent() increment the counter for an already present key?

Running this example code (from Cay Horstmann)运行此示例代码(来自 Cay Horstmann)

ConcurrentHashMap<String,LongAdder> counts = new ConcurrentHashMap<>();
for (String key : "Row, row, row a boat".split("\\PL+"))
    counts.computeIfAbsent(key, k -> new LongAdder()).increment();
System.out.println(counts);

The output is输出是

{a=1, Row=1, row=2, boat=1}

I am surprised to see row=2 because I expected computeIfAbsent() would increment only when it found the first "row" and not the second one.看到row=2我很惊讶,因为我预计 computeIfAbsent() 只会在它找到第一个“行”而不是第二个“行”时增加。

counts.computeIfAbsent(key, k -> new LongAdder())

This entire expression can go one of two ways:整个表达式可以采用以下两种方式之一:

  1. key is already in the counts map. key已经在counts映射中。 In this case, the 'computer' function ( k -> new LongAdder() ) is completely ignored;在这种情况下,“计算机”函数( k -> new LongAdder() )被完全忽略; it isn't run at all.它根本没有运行。 Instead, the value associated with that key is returned.而是返回与该键关联的值。

  2. key is not in the counts map. key不在counts映射中。 In this case, the 'computer' function is executed once, and the value it returns is now associated with the key.在这种情况下,“计算机”函数执行一次,它返回的值现在与键相关联。

In other words, it's identical to:换句话说,它等同于:

LongAdder result;
if (counts.containsKey(key)) result = counts.get(key);
else {
  result = new LongAdder();
  counts.put(key, result);
}
return result;

Which is a mouthful, potentially less efficient, and potentially non-atomic whereas .computerIfAbsent can be atomic if you use the right implementation (such as ConcurrentHashMap ).如果您使用正确的实现(例如ConcurrentHashMap ),这是一个拗口的,可能效率较低且可能不是原子的,而.computerIfAbsent可以是原子的。

Here's the clue: You then invoke .increment() on this result, regardless of whether we're in the #1 case or the #2 case .线索如下:然后你调用.increment()这个结果,不管我们是在#1 case 还是#2 case

In other words:换句话说:

First 'row' is seen, computeIfAbsent ends up executing the lambda and thus, runs something like counts.put(k, new LongAdder()) and THEN you call .increment() on this.看到第一个“行”, computeIfAbsent最终执行 lambda,因此运行类似counts.put(k, new LongAdder())的东西,然后你调用.increment()

Next, the second 'row' is seen, computeIfAbsent ends up being equivalent to counts.get(key) , and you call .increment() on that.接下来,看到第二个“行”, computeIfAbsent最终等同于counts.get(key) ,然后您调用.increment() Which is the same LongAdder we made when we saw the first 'row', and thus this is the second time you are invoking increment() on it.这与我们看到第一行时制作的 LongAdder 相同,因此这是您第二次在其上调用increment()

It's not computeIfAbsent that's incrementing anything.增加任何东西的不是computeIfAbsent It's the .increment() that increments something..increment()增加一些东西。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 ConcurrentHashMap.computeIfAbsent threadsafe中的赋值是什么? - Is an assignment inside ConcurrentHashMap.computeIfAbsent threadsafe? 在ConcurrentHashMap.computeIfAbsent和ConcurrentHashMap.computeIfPresent中执行`mappingFunction` - Execution of `mappingFunction` in ConcurrentHashMap.computeIfAbsent and ConcurrentHashMap.computeIfPresent 如何在不将条目分配给 hashmap 的情况下执行 ConcurrentHashMap.computeIfAbsent? - How to do ConcurrentHashMap.computeIfAbsent without assigning the entry to hashmap? 递归ConcurrentHashMap.computeIfAbsent()调用永远不会终止。 错误还是“功能”? - Recursive ConcurrentHashMap.computeIfAbsent() call never terminates. Bug or “feature”? Java ConcurrentHashMap computeIfAbsent() 方法是否支持基于键的“锁定”? - Does Java ConcurrentHashMap computeIfAbsent() method support key-based “locking”? 为什么 ConcurrentHashMap::putIfAbsent 比 ConcurrentHashMap::computeIfAbsent 快? - Why ConcurrentHashMap::putIfAbsent is faster than ConcurrentHashMap::computeIfAbsent? ConcurrentHashMap computeIfAbsent - ConcurrentHashMap computeIfAbsent computeIfAbsent 如何随机使 ConcurrentHashMap 失败? - How does computeIfAbsent fail ConcurrentHashMap randomly? 为什么ConcurrentHashMap中的computeIfAbsent()方法行为不一致? - Why is the computeIfAbsent() method in ConcurrentHashMap behaving inconsistently? 更新ConcurrentHashMap中的其他键的后果#computeIfAbsent - Consequences of updating other key(s) in ConcurrentHashMap#computeIfAbsent
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM