首先要了解HashMap的擴容過程,我們就得了解一些HashMap中的變量:
Node<K,V>:鏈表節點,包含了key、value、hash、next指針四個元素 table:Node<K,V>類型的數組,里面的元素是鏈表,用於存放HashMap元素的實體 size:記錄了放入HashMap的元素個數 loadFactor:負載因子 threshold:擴容的閾值,決定了HashMap何時擴容,以及擴容后的大小,一般等於,等於 table * loadFactor
何時進行擴容?
HashMap使用的是懶加載,構造完HashMap對象后,只要不進行put 方法插入元素之前,HashMap並不會去初始化或者擴容table。
當首次調用put方法時,HashMap會發現table為空然后調用resize方法進行初始化,當添加完元素后,如果HashMap發現size(元素總數)大於threshold(閾值),則會調用resize方法進行擴容
擴容過程:
- 若threshold(閾值)不為空,table的首次初始化大小為閾值,否則初始化為缺省值大小16
- 默認的負載因子大小為0.75,當一個map填滿了75%的bucket時候,就會擴容,擴容后的table大小變為原來的兩倍
擴容因子=0.75。當使用量接近數組容量的75%的時候,數組中還有25%的剩余空間。碰撞的概率越大,put的元素就越多,平均到每個桶中的元素的數量也越多。一旦發生碰撞,需要付出更大的代價。所以,如果擴容因子越大,碰撞的概率也就越大,發生碰撞后的代價也更大,結果導致效率大打折扣。因此擴容因子=0.75也是一個空間換時間的考慮,0.75這個數值應該是經過充分的考慮決定的。
- 假設擴容前的table大小為2的N次方,有上述put方法解析可知,元素的table索引為其hash值的后N位確定
- 擴容后的table大小即為2的N+1次方,則其中元素的table索引為其hash值的后N+1位確定,比原來多了一位
- 重新調整map的大小,並將原來的對象放入新的bucket數組中。這個過程叫作rehashing
因此,table中的元素只有兩種情況:
元素hash值第N+1位為0:不需要進行位置調整
元素hash值第N+1位為1:調整至原索引的兩倍位置
擴容或初始化完成后,resize方法返回新的table