Java中HashMap擴容機制思考


1. HashMap在什么條件下擴容

判斷HashMap的數組Size大小如果超過loadFactor*capacity,就要擴容。

相關的類屬性:

  • capacity:當前數組容量,始終保持 2^n,可以擴容,擴容后數組大小為當前的 2 倍。

  • loadFactor:負載因子,默認為 0.75

    loadFactor加載因子是控制數組存放數據的疏密程度,loadFactor越趨近於1,那么 數組中存放的數據(entry)也就越多,也就越密,也就是會讓鏈表的長度增加,loadFactor越小,也就是趨近於0,數組中存放的數據(entry)也就越少,也就越稀疏。

    loadFactor太大導致查找元素效率低,太小導致數組的利用率低,存放的數據會很分散。loadFactor的默認值為0.75f是官方給出的一個比較好的臨界值

    給定的默認容量為 16,負載因子為 0.75。Map 在使用過程中不斷的往里面存放數據,當數量達到了 16 * 0.75 = 12 就需要將當前 16 的容量進行擴容,而擴容這個過程涉及到 rehash、復制數據等操作,所以非常消耗性能。

  • threshold:擴容的閾值

    threshold = capacity * loadFactor,當Size>=threshold的時候,那么就要對數組擴增了。

2. HashMap 的長度為什么是2的冪次方

為了能讓 HashMap 存取高效,盡量減少碰撞,把數據分配均勻,利用擾動函數hash方法對key進行處理得到Hash值Hash 值的范圍值-2147483648到2147483647,前后加起來大概40億的映射空間,只要哈希函數映射得比較均勻松散,一般應用是很難出現碰撞的。但問題是一個40億長度的數組,內存是放不下的。所以這個散列值是不能直接拿來用的。用之前還要先做對數組的長度取模運算,得到的余數才能用來要存放的位置也就是對應的數組下標。這個數組下標的計算方法是“ (n - 1) & hash”。(n代表數組長度)

取余(%)操作中如果除數是2的冪次則等價於與其除數減一的與(&)操作(也就是說 hash%length==hash&(length-1)的前提是:length 是2的 n 次方),且采用二進制位操作 &,相對於%能夠提高運算效率,這就解釋了 HashMap 的長度為什么是2的冪次方。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM