簡體   English   中英

對Java8中的HashMap感到困惑

[英]Confused about HashMap in Java8

我有一個哈希圖,將String和HashSet作為鍵和值。 我正在嘗試更新地圖並在其中添加值。

我無法理解使用以下哪種方法-

  1. map.putIfAbsent(str.substring(i,j),new HashSet<String>).add(str); //this method gives nullpointerexception

  2. map.computeIfPresent(str.substring(i,j),(k,v)->v).add(str);

在輸出中,我可以看到同一鍵被兩次添加了初始值和更新值。

有人請告訴我如何使用這些方法。

最好的方法是使用Map#computeIfAbsent 這樣,就不必不必要地創建新的HashSet ,它將在之后返回該值。

map.computeIfAbsent(str.substring(i, j), k -> new HashSet<>()).add(str);

沒有理由在putIfAbsentcomputeIfPresent之間進行選擇。 最值得注意的是, computeIfPresentcomputeIfPresent完全不合適,它僅在已經存在舊值時才計算新值,並且(k,v)->v甚至使該計算成為無操作。

有幾種選擇

  1. containsKeyputget 這是Java 8之前最流行的版本,盡管它在此列表中效率最低,因為它為同一密鑰最多合並了三個哈希查找

     String key=str.substring(i, j); if(!map.containsKey(key)) map.put(key, new HashSet<>()); map.get(key).add(str); 
  2. get put 比第一個更好,盡管它仍然可以包含兩個查詢。 對於普通Map ,這是Java 8之前的最佳選擇:

     String key=str.substring(i, j); Set<String> set=map.get(key); if(set==null) map.put(key, set=new HashSet<>()); set.add(str); 
  3. putIfAbsent 在Java 8之前,此選項僅對ConcurrentMap可用。

     String key=str.substring(i, j); Set<String> set=new HashSet<>(), old=map.putIfAbsent(key, set); (old!=null? old: set).add(str); 

    這僅進行一次哈希查找,但是即使我們不需要它,也需要無條件創建新的HashSet 在這里,可能值得先執行一次get來推遲創建,尤其是在使用ConcurrentMap ,因為可以無鎖執行get並可能使隨后的更昂貴的putIfAbsent不必要。

    另一方面,必須強調的是,此構造不是線程安全的,因為對值Set的操縱不受任何保護。

  4. computeIfAbsent 此Java 8方法允許最簡潔,最有效的操作:

     map.computeIfAbsent(str.substring(i, j), k -> new HashSet<>()).add(str); 

    這只會評估函數,如果沒有舊值,並且與putIfAbsent不同,此方法將返回新值,如果沒有舊值,換句話說,無論哪種情況,它都會返回正確的Set ,因此我們可以直接add對此。 盡管如此, add操作還是在Map操作之外執行的,因此即使Map是線程安全的,也沒有線程安全。 但是對於普通Map ,即如果不考慮線程安全性,則這是最有效的變體。

  5. compute 此Java 8方法將始終評估函數,並且可以通過兩種方式使用。 第一個

     map.compute(str.substring(i, j), (k,v) -> v==null? new HashSet<>(): v).add(str); 

    只是computeIfAbsent的更詳細的變體。 第二

     map.compute(str.substring(i, j), (k,v) -> { if(v==null) v=new HashSet<>(); v.add(str); return v; }); 

    將在Map的線程安全策略下執行Set更新,因此在ConcurrentHashMap情況下,這將是線程安全的更新,因此,當考慮到線程安全時,使用compute而不是computeIfAbsent具有有效的用例。

暫無
暫無

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

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