簡體   English   中英

如果我們在重新散列發生時放置一個元素,在 HashMap 中會發生什么?

[英]What will happen in HashMap , if we put an element while rehashing is happening?

我想知道當調整大小或重新哈希時,如果我們嘗試將一個元素放入地圖中會發生什么。它會轉到新增加的地圖還是舊地圖。

以及 hashmap 中額外可用空間的用途是什么,它是原始地圖大小的 25%,因為負載因子是 75%?

也許這需要一個連貫的答案。

我想知道在調整大小或重新哈希時發生什么,如果我們嘗試將元素放入地圖中會發生什么。

只有當您有兩個或更多線程在HashMap上執行操作時,這個問題才有意義。 如果您這樣做,您的代碼不是線程安全的。 它的行為是未指定的、特定於版本的,並且您可能會在不可預測的時間發生壞事。 諸如條目丟失、莫名其妙的 NPE、甚至您的線程之一進入無限循環之類的事情。

您不應該編寫兩個或多個線程在沒有適當外部同步的情況下對HashMap進行操作的代碼,以避免同時操作。 如果你這樣做了,我不能告訴你會發生什么。

如果您只有一個線程使用HashMap ,那么您擔心的場景是不可能的。 調整大小發生在更新操作期間。

如果您有多個線程並進行同步以防止任何同時操作,那么您所關心的場景是不可能的。 另一種選擇是使用ConcurrentHashMap ,它旨在在多個線程可以同時紅色和寫入時正常工作。 (當然,調整ConcurrentHashMap大小的代碼要復雜得多。但它可以確保條目最終出現在正確的位置。)

是去新增加的地圖還是舊地圖。

假設您在談論多線程非同步情況,答案是未指定的並且可能是特定於版本的。 (我沒有檢查代碼。)對於其他情況,這種情況是不可能的。


以及 hashmap 中額外可用空間的用途是什么,它是原始地圖大小的 25%,因為負載因子是 75%?

它沒有被使用。 如果負載因子為 75%,則至少 25% 的哈希槽將為空/從未使用。 (直到您達到由於架構原因無法進一步擴展哈希數組的程度。但您很少會達到該程度。)

這是一個性能權衡。 Sun 工程師確定/判斷 75% 的負載因子將在使用的內存和在HashMap上執行操作所花費的時間之間提供最佳權衡。 隨着負載因子的增加,空間利用率會提高,但HashMap上的大多數操作會變慢,因為哈希鏈的平均長度會增加。

如果需要,您可以自由使用不同的負載因子值。 請注意潛在的后果。

調整大小和多線程

如果您從單個線程訪問哈希映射,則它不會發生。 調整大小不是由計時器觸發,而是由更改哈希映射中元素數量的操作觸發,例如由put()操作觸發。 如果您調用put()並且哈希映射看到需要調整大小,它將執行調整大小,然后它將執行您的新元素。 意味着,調整大小后將添加新元素,不會丟失任何元素,任何方法都會出現不一致的行為。

Buf 如果從多個線程訪問您的哈希映射,那么可能會出現多種問題。 例如,如果兩個線程同時調用put() ,兩者都可以觸發調整大小。 后果之一可能是其中一個線程的新元素將丟失。 即使不需要調整大小,多線程也會導致丟失某些元素。 例如,兩個線程生成相同的桶索引,而目前還沒有這樣的桶。 兩個線程都創建了這樣的存儲桶並將其添加到存儲桶數組中。 但是最近的勝利,另一個將被覆蓋。

它不是特定於哈希映射的。 當你通過多個線程修改對象時,這是一個典型的問題。 要在多線程環境中正確處理哈希映射,您可以實現同步或使用已經是線程安全的類ConcurrentHashMap

負載系數

哈希映射中的元素存儲在桶中。 如果每個散列對應於單個桶索引,則訪問時間為O(1) 您擁有的哈希越多,兩個哈希產生相同桶索引的概率就越高。 然后它們會存儲在同一個桶中,訪問時間會增加

減少此類沖突的一種解決方案是使用另一種散列函數。 但是 1) 設計適合特定要求的散列函數可能是一項非常重要的任務(除了減少沖突之外,它還應該提供可接受的性能),並且 2) 您只能在自己的類中改進散列,而不能在您使用的庫中改進。

另一個更簡單的解決方案是對相同數量的散列使用更多數量的桶。 當您減少關系(哈希數) / (桶數) 時,您會減少沖突的可能性,從而使訪問時間接近O(1) 但代價是,你需要更多的內存。 例如,對於 75% 的負載因子,不使用桶數組的 25%; 對於 10% 的負載系數,將不使用 90%。

沒有適合所有情況的解決方案。 嘗試不同的值並測量性能和內存使用情況,然后決定哪種情況更適合您的情況。

暫無
暫無

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

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