簡體   English   中英

為什么 ConcurrentHashMap.computeIfAbsent() 為已經存在的鍵增加計數器?

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

運行此示例代碼(來自 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);

輸出是

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

看到row=2我很驚訝,因為我預計 computeIfAbsent() 只會在它找到第一個“行”而不是第二個“行”時增加。

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

整個表達式可以采用以下兩種方式之一:

  1. key已經在counts映射中。 在這種情況下,“計算機”函數( k -> new LongAdder() )被完全忽略; 它根本沒有運行。 而是返回與該鍵關聯的值。

  2. key不在counts映射中。 在這種情況下,“計算機”函數執行一次,它返回的值現在與鍵相關聯。

換句話說,它等同於:

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

如果您使用正確的實現(例如ConcurrentHashMap ),這是一個拗口的,可能效率較低且可能不是原子的,而.computerIfAbsent可以是原子的。

線索如下:然后你調用.increment()這個結果,不管我們是在#1 case 還是#2 case

換句話說:

看到第一個“行”, computeIfAbsent最終執行 lambda,因此運行類似counts.put(k, new LongAdder())的東西,然后你調用.increment()

接下來,看到第二個“行”, computeIfAbsent最終等同於counts.get(key) ,然后您調用.increment() 這與我們看到第一行時制作的 LongAdder 相同,因此這是您第二次在其上調用increment()

增加任何東西的不是computeIfAbsent .increment()增加一些東西。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM