hashmap底層實現採用的是雜湊表(基本結構就是「陣列+鍊錶」)。
乙個entry物件儲存了:
1、key:鍵物件value:值物件
3、hash值物件的hash值。
顯然每乙個entry物件就是乙個單向鍊錶結構,我們使用圖形表示乙個entry物件的典型示意:
然後,我們畫出entry陣列的結構(這也是hashmap的結構):在這裡我們把單向鍊錶儲存在乙個陣列裡面。
明白了hashmap的基本結構後,我們繼續深入學習hashmap如何儲存資料的。此處的核心是如何產生hash值,該值用來對應陣列的儲存位置。
我們的目的是將「key-value兩個物件」 成對的存放到hashmap扥entry陣列中,參見以下步驟:
首先呼叫key物件的hashcode()方法,獲得hashcode。
hashcode是乙個整數,我們需要將它轉化成[0,陣列長度-1]區間)的範圍。我們要求轉化後的hash值盡量均勻地分布在[0,陣列長度-1]區間),減少「hash衝突」。
public class test
public static int myhash(int h,int length)
}
執行上面的程式,我們發現直接取餘h%length和位運算+(h&(length-1))結果是一致的。事實是為了獲得更好的雜湊效果。
如果本entry物件對應的陣列索引位置還沒有放entry物件,則直接將entry物件儲存進陣列;如果對應索引位置已經有entry物件,則將已有entry物件的next指向本entry物件,形成鍊錶。
當新增乙個元素(key-value)時,首先計算key的hash值,以此確定插入陣列中的位置,但是可能存在同乙個hash值的元素已經放在同一位置了,這是就新增到同一hash值元素的後面,他們在陣列同乙個位置,就形成了鍊錶,同乙個鍊錶上的hash值是相同的,所以說陣列存放的是鍊錶。
我們需要通過key物件獲得「鍵值對」物件,進而返回value物件,明白了儲存資料過程,去資料過程就比較簡單了,參見以下步驟:
hashmap的位桶陣列,初始大小為16.實際使用時,顯然大小是可變的。如果位桶陣列中的元素達到(0.75*陣列length),就重新調整陣列大小變為原來2倍大小。
擴容很耗時的,擴容的額本質是定義新的更大的陣列,並將舊的陣列內容挨個拷貝到新的陣列中。
獲得key的hashcode,通過hash()雜湊演算法得到hash值,進而定位到陣列的位置。在鍊錶上挨個比較key物件。呼叫equel()方法,將key物件和鍊錶上所有節點的key物件進行比較,直到碰到返回 true的節點物件為止。返回equel()為true的節點物件的value物件。
HashMap轉移資料的過程
確定需要擴容之後,先計算原來陣列的長度,如果已經等於最大值了那就不可能再擴容了,直接返回。如果不是,創新乙個新的新長度的陣列。然後執行轉移方法。轉移方法 for迴圈遍歷原陣列,遍歷每乙個entry,首先儲存entry中的下乙個entry。下一次需要迴圈的 判斷是否需要重新計算hash值,如果需要就重...
HashMap的resize 過程簡述版本
將integer.max value賦給閾值,返回舊表 這個比較有意思,涉及到hashmap的幾種初始化,深入說一下。1 如果使用public hashmap 初始化表,oldcap為0,oldthr也為0,會走到下乙個分支 第4點 2 如果使用public hashmap int initialc...
Oracle儲存過程訪問,Oracle資料分頁
訪問oracle的儲存過程並獲取返回結果 using oracleconnection cn new oracleconnection connectionstringlocaltransaction parameters 0 value value 輸入引數的值 parameters 0 dire...