當數組表的大小達到閾值時,為++ size》;負載系數*容量也在putVal函數中。
擴展需要重新分配壹個新數組,該數組的長度是舊數組的兩倍,然後遍歷整個舊結構並將所有元素逐個散列到新結構中。
散列關鍵字的hashCode,並計算下標以獲得桶的位置。如果可以在桶的頂部找到它,它將直接返回,否則,將在樹或鏈表中搜索它。如果有哈希沖突,它將使用equals方法遍歷鏈表來查找節點。
散列key的hashCode,並將其與高16位進行XOR運算。
還有平方法、除法和余數法以及偽隨機數法。
因為數組位置由AND運算確定,並且只有最後四位有效,所以設計者將key的哈希值與高位16進行XOR運算,因此設計者正在做的是&在計算數組的插入位置時,低位實際上是高位和低位的組合,這增加了隨機性並減少了哈希沖突的次數。
將發生哈希沖突。如果鍵值相同,舊值將被替換。否則,它將鏈接到鏈表的後面。如果鏈表的長度超過閾值8,它將被存儲為紅黑樹。
HashCode也是壹樣的,value對象是通過equals比較內容得到的。
如果超過閾值,它將被擴展。壹般來說,擴展數組的大小是原始數組的兩倍,原始元素將被再次哈希並放入新的哈希表中。
相似之處:它們都存儲鍵值對。
差異:
LoadFactor表示HashMap的擁塞程度,它影響對同壹數組位置進行哈希操作的概率。默認負載系數等於0.75。當HashMap中包含的元素達到HashMap數組長度的75%時,意味著HashMap過於擁擠,需要擴展。您可以在HashMap的構造函數中自定義loadFactor。
在JDK 1.8之前,HashMap的實現是數組+鏈表。即使很好地獲得了哈希函數,也很難實現元素的100%均勻分布。當HashMap中的大量元素存儲在同壹個桶中時,這個桶下有壹個長鏈表。此時,HashMap相當於單個鏈表。如果單鏈表有n個元素,遍歷的時間復雜度為O(n),就完全失去了優勢。針對這種情況,JDK 1.8引入了紅黑樹(搜索時間復雜度為O(logn))來優化這個問題。但是鏈表大於8的概率非常非常低。
選擇不可變類型如Integer和String,如對String的所有操作都是創建壹個新的String對象、拼接和拆分新對象等。這些類已經以標準化的方式涵蓋了hashCode()和equals()方法。作為壹個不可變的類本質上是線程安全的。如果您想使用自定義類作為鍵,則需要重寫hashCode()和equals()方法。紅黑樹在進行比較時使用System.identityHashCode()方法,不需要特殊處理。
更多內容戳這裏(各類收藏作品)