对HashMap数据结构的理解——加载因子和初始容量
先看源碼:
解釋一下位移運算:
1<<4 是位移運算的表示,為十進制16
1的二進制表示:1
左移4位之后的二進制表示為B(10000) = D(16)
更簡單的計算方法就是 1<< n 等效于 1 乘以 2的 n 次方
進入正題
HashMap底層數據結構是數組+鏈表,JDK1.8中還引入了紅黑樹,當鏈表長度超過8個時,會將鏈表轉成紅黑樹,以提升其查找性能。
HashMap有兩個參數影響其性能:初始容量和加載因子。
1、HashMap的初始容量
容量是哈希表中桶的數量,初始容量只是哈希表在創建時的容量。
2、HashMap的加載因子
加載因子是哈希表在其容量自動擴容之前可以達到多滿的一種度量。
3、作用
當哈希表中的條目數超出了加載因子與當前容量的乘積時,則要對該哈希表進行擴容、rehash操作(即重建內部數據結構),擴容后的哈希表容量為原來的兩倍。
為了減少沖突的概率,當HashMap的數組長度到了一個臨界值就會觸發擴容,把所有元素rehash再放到擴容后的容器中,所以說rehash是一個非常耗時的操作。
而這個臨界值是由加載因子和當前容器的容量大小來確定:
DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR
即默認情況下是 16x0.75 =12 時,就會觸發擴容操作。
4、面試高頻:為什么加載因子初始化是0.75呢?
- 也是一個綜合考慮,如果設置過小如0.5,HashMap 每 put 少量的數據,都要進行一次擴容,而擴容操作會消耗大量的性能。使得空間利用率很低,同時提高了rehash(重建內部數據結構)操作的次數。
- 如果設置過大的話,比如設成1,容量還是16,假設現在數組上已經占用了15個,再要put數據進來,計算數組 index 時,發生 hash碰撞 的概率將達到15/16,這違背了 HashMap 減少 hash碰撞 的原則。同時,這樣會減少空間開銷,提高空間利用率,但同時會增加查詢時間的成本。
- 因此,選擇0.75作為默認的加載因子,完全是時間和空間成本上尋求折中的選擇。
- 在設置初始容量時應該考慮到映射中所需的條目數及其加載因子,以便最大限度地減少rehash操作次數,所以,一般在使用HashMap時建議根據預估值設置初始容量,減少擴容操作。
4、面試高頻:為什么初始容量是16
當容量為2的冪次方時,源碼中 n -1 對應的二進制數全為1,這樣才能保證它和 key 的 hashcode 做&運算后,能夠均勻分布,這樣才能減少hash碰撞的次數。至于默認值為什么是16,而不是2 、4、8,或者32、64、1024等,應該就是個折中處理,過小會導致放不下幾個元素,就要進行擴容了,而擴容是一個很消耗性能的操作。取值過大的話,無疑會浪費更多的內存空間。因此在日常開發中,如果可以預估HashMap會存入節點的數量,則應該在初始化時,指定其容量。
參考原文:
HashMap容量和負載因子:https://blog.csdn.net/ye17186/article/details/88876417
HashMap中的初始容量和加載因子:https://blog.csdn.net/weixin_44723496/article/details/112387738
總結
以上是生活随笔為你收集整理的对HashMap数据结构的理解——加载因子和初始容量的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 八皇后问题和八数码问题的最陡上升爬山法、
- 下一篇: 深入了解EntityFramework—