HashMap(jdk1.8)

hashmap在1.8中是以數組+鏈表+紅黑樹的結構實現的,在數組中的存放位置是用hash屬性&長度-1 去尋址的(因爲長度是2的冪,加上尋址方式,方便擴容,擴容兩倍後數據不在原來位置就在原來位置X2的地方),允許key爲null,但是只能有一個;value可以null,不限個數。

hashmap無參構造初始化時啥沒有,只有put時纔會調用resize()纔會有長度,默認16

一接口

實現了

Map<K,V>, Cloneable, Serializable 接口

繼承

AbstractMap類

二 內部一些屬性

DEFAULT_INITIAL_CAPACITY 默認長度,16,2的冪,原因是爲了擴容(後面說),尋址碰撞
MAXIMUM_CAPACITY 最大長度,2^30=1 073 741 824
DEFAULT_LOAD_FACTOR = 0.75f; 負載因子
TREEIFY_THRESHOLD = 8; 鏈表向紅黑樹轉化的閥值
UNTREEIFY_THRESHOLD = 6;紅黑樹轉化成鏈表的閥值
Node<K,V>[] table; node的數組,存放具體的值,
threshold 負載數量,容量*負載因子
size 長度。數組裏放了多少個值

MIN_TREEIFY_CAPACITY=64  轉爲紅黑樹的時候最小長度

數組

size 記錄長度

modCount記錄操作數

還有靜態內部類Node,存儲數據,key,value,hash,next(鏈表,指向下一個數據)

hash(),

計算hash值,獲取key.hashCode()^(key.hashCode()>>>16)(異或操作,計算快,key 爲null返回0)

put() ,

1.首先判斷table是否已經初始化,否則調用resize(),進行初始化。

2.獲取key對應位置的值,null就實例化一個新的node放進去,如果不null,或取得數據判斷hash是否相等equals,是的話取得當前值,不是的話就要遍歷了,(簡單的說就是看看當前位置是不是沒有hash衝突,當前位置不是鏈表也不是紅黑樹)當前位置空就直接放進去;如果是紅黑樹,調用putTreeVal()方法;已經有值的話就是個鏈表,當前位置node.next賦值爲當前對象,並進行判斷鏈表長度達到8,轉化成紅黑樹;

3.判斷(++size > threshold),根據條件進行判斷是否需要擴容(2倍)

4.treeifyBin()

轉化紅黑樹的時候,table長度最少要到64

if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
    resize();
resize()

擴容,

1.初始擴容,默認16

2.已經是最大長度了,不在擴容。

3..長度沒達到最大長度,*2 也沒達到最大長度。擴容兩倍

擴容是指重新構造一個新的數組(兩倍原數組),將原數組遍歷重新分配到新數組裏,因爲是兩倍擴容,並且長度時2的冪,尋址時又是獲取node.hash&(容量-1),使得數據不在當前位置就在原位置的2倍的地方,減少移動。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章