更新時間:2022-01-05 11:45:04 來源:動力節點 瀏覽2055次
當 hashmap 中的元素數量超過數組大小 * loadFactor 時,Java數組擴容。loadFactor的默認值是_ LOAD_ 當hashmap中的元素個數超過16 * 0.75 = 12(閾值或邊界值)時,將數組的大小擴展為2 * 16 = 32,然后重新計算每個元素在hashmap中的位置數組。這是一個非常消耗性能的操作,所以我們最好能夠提前預測和設置元素的數量。
注意:
當hashmap中一個鏈表的對象個數達到8個時,如果數組長度沒有達到64,那么hashmap會先展開。如果達到64,就會變成紅黑樹,Node類型從Node變成TreeNode。當然,如果去掉映射關系,下一次執行reset()方法時,會判斷樹中的節點數小于6,也會將樹轉換為鏈表
擴展會伴隨著新的hash分配,會遍歷hash表中的所有元素,非常耗時。在編寫程序的過程中,我們應該盡量避免resize()
每次擴充一倍,與原來的(n-1)&hash結果相比,只多了一位,所以節點要么在原來的位置,要么會被分配到“原來的位置+舊容量”的位置
原始數組長度:16 n = n - 1 ---> 15
(n - 1) & 散列
0000 0000 0000 0000 0000 0000 0001 0000 16
0000 0000 0000 0000 0000 0000 0000 1111 15 n - 1
hash1 (key1):1111 1111 1111 1111 0000 1111 0000 0101
-------------------------------------------------- --------------
0000 0000 0000 0000 0000 0000 0000 1111 索引 5
0000 0000 0000 0000 0000 0000 0000 1111 15 n - 1
hash2 (key2):1111 1111 1111 1111 0000 1111 0000 0101
-------------------------------------------------- --------------
0000 0000 0000 0000 0000 0000 0000 1111 索引 5
================================================== ==============
數組長度擴展——> 16 * 32 n - 1 ---> 31
(n - 1) & 散列
0000 0000 0000 0000 0000 0000 0010 0000 32
0000 0000 0000 0000 0000 0000 0001 1111 31 n - 1
hash1(key1): 1111 1111 1111 1111 0000 1111 0000 0101
-------------------------------------------------- --------------
0000 0000 0000 0000 0000 0000 0000 0101 索引 5
0000 0000 0000 0000 0000 0000 0001 1111 31 n - 1
hash2 (key2):1111 1111 1111 1111 0000 1111 0000 0101
-------------------------------------------------- --------------
0000 0000 0000 0000 0000 0000 0001 0101 指數 5 + 16
所以,元素重新計算hash后,因為N變成了兩倍,n-1的標簽范圍比高位多1位,所以新的索引會變成這樣
原來的位置=原來的位置+oldCap
注:5 為假設計算出的原始指標值,以驗證功能描述。擴容后節點要么在原位置,要么分配到“原位置+舊容量”位置
因此,我們在展開hash map時,不需要重新計算hash值。我們只需要看原始哈希值的新位是1還是0,
(0表示索引沒有變化,1表示原始索引+舊容量)
因為這種巧妙的rehash方法,不僅節省了重新計算hash值的時間,而且新的1位是0或1
這是隨機的。在reszie的過程中,保證rehash后每個bucket上的節點數必須小于等于原bucket上的節點數,從而保證rehash后不會出現更嚴重的hash沖突,并將之前的沖突節點均勻地分散到新的bucket中。
HashMap 的擴展機制是在滿足擴展條件時進行擴展。HashMap 的擴展條件是當HashMap 中的元素個數超過閾值時,會自動擴展。因此,如果我們不設置初始容量,隨著元素數量的增加,HashMap 可能會擴展數倍。HashMap 中的擴展機制決定了每次都需要重新構建哈希表,極大地影響了性能。
可以認為,當我們知道HashMap中的元素個數時,將默認容量設置為initialCapacity/0.75F+1.0F從性能上來說是一個比較好的選擇,但也會犧牲一些內存。
Jdk 并沒有直接將用戶傳入的數作為默認容量,而是會進行一些計算,最終得到一個 2 的冪。
例子:
initalCapacity =(要存儲的元素數/負載因子)+ 1
默認情況下,負載因子為 0.75。如果暫時不能確定大小,建議設置為16
如果開始時沒有指定初始化因子。當需要放置1024個元素時,隨著元素數量的增加,需要擴容7倍并重建哈希表,嚴重影響性能。
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習