HashMap 數據結構
Jdk1.8之前:數組+鏈表
Jdk 1.8之後 數組+鏈表+紅黑書
鏈表長度大於8後並且數組長度 大於64 鏈表結構轉化成紅黑樹結構
爲什麼jdk8之後要用紅黑樹
因爲鏈表插入快,查詢慢,當鏈表太長時,
相當於 node.next.next.next.next.next.next.next.next …… = new Node(xx)
其中next就相當於插入,而紅黑數可以通過左旋右旋的方式減少查找深度
Hash算法
Hash算法也叫散列算法,就是把任意長度值(Key)通過散列算法變幻成固定長度的key值,通過這個地址進行訪問的數據結構。它通過把關鍵碼值映射到表中的一個位置來訪問記錄,達到加快查找的速度。這個映射函數叫散列函數,存放記錄的數組叫散列表。
put方法圖解
鏈表存儲說明
以下代碼是hashmap在put數據時摘抄的一部分邏輯
// 當產生hash碰撞的情況下的一部分處理邏輯
for (int binCount = 0; ; ++binCount) {
//遍歷當前桶中的所有節點
if ((e = p.next) == null) {
//如果當前索引對應節點的next爲null的情況,即當前索引對應的鏈表中只保存了一個節點
//將當前put的key value 創建新的節點(next 爲null),原來節點的next指向該新節點
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1)
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
HashMap map = new HashMap<>() 的執行過程
jdk8之前:
構造方法中創建了一個長度是16的Entry[] table 用來存儲鍵值對數據。
jdk8之後:
不在構造方法中創建,在第一次put方法時創建的 Node[] table 來保存數據。
調用put 時保存數據的過程
put的數據在數組中的位置是根據 key 調用String類中的重寫之後的hashCode()方法計算出的值,然後結合數組長度結合某種算法計算出對應的index值來確定數組中的位置。
如果之後put的key計算出的索引和原來的一致,此時會比較兩個hash值是否相等,如果不想等,則在此索引位置對應的空間劃一個節點來保存該數據。如果hash值相等,則發生hash碰撞,這時會調用String中的equals方法比較兩個值得內容是否相等,如果比較的內容相等,則覆蓋原來的,如果不想等,繼續向下和其它的數據key進行比較,如果都不想等,則劃出一個節點存儲數據
總結: