昨天的部落格我解釋了hashmap(jdk1.7)在put的時候會發生衝突,而解決衝突的方式就是使用鍊錶,那麼我們假設hashmap儲存結構如下圖:
那麼節點1和節點2組成了乙個鍊錶,那麼現在如果再來put乙個節點3,假設節點3也需要插在這個鍊錶中,我們考慮鍊錶的插入效率,將節點3插在鍊錶的頭部是最快的,那麼就會如下圖:
那麼按照上圖這種插入辦法,會出現乙個問題:
那hashmap是怎麼實現的呢?hashmap確實是將節點插在鍊錶的頭部,但是在插完之後hashmap會將整個鍊錶向下移動一位,移動完之後就會變成:
那麼現在put的時候插入乙個元素的思路就是:將新節點插在鍊錶的頭部,此時新節點就是當前這個鍊錶的頭節點,接下來把頭節點移動到陣列位置即可。
當我們在使用hashmap的時候,還可能會出現下面的使用方式:
hashmap hashmap = new hashmap<>();第三行**也是put,而這個時候在hashmap裡會將value覆蓋,也就是key="1"對應的value最終為"3",而第三行**返回的value將會是2。hashmap.put("1", "2");
string value = hashmap.put("1", "3");
system.out.println(value);
我們現在來考慮這個put它是如何實現的,其實很簡單,第三行**的邏輯也是先對"1"計算雜湊值以及對應的陣列下標,有了陣列下標之後就可以找到對應的位置的鍊錶,而在將新節點插入到鍊錶之前,還需要判斷一下當前新節點的key值是不是已經在這個鍊錶上存在,所以需要先去遍歷當前這個位置的鍊錶,在遍歷的過程中如果找到了相同的key則會進行value的覆蓋,並且返回oldvalue。
好,寫到這裡其實對於hashmap的put的主要邏輯也差不多了,總結一下:
put(key,value)
int hashcode = key.hashcode();
int index = hashcode & (陣列長度-1)
遍歷index位置的鍊錶,如果存在相同的key,則進行value覆蓋,並且返回之前的value值
將key,value封裝為節點物件(entry)
將節點插在index位置上的鍊錶的頭部
將煉表頭節點移動到陣列上
這是最核心的7步,然後在這個過程中還有很重要的一步就是擴容,而擴容是發生在插入節點之前的,也就是步驟4和5之間的。
那麼關於jdk1.7裡hashmap的擴容時會出現「死鎖」問題的,我們下篇文章繼續。
HashMap JDK1 7原始碼分析
hashmapjdk原始碼分析 建構函式 底層資料結構 基本屬性 擴容方式 預設值繼承關係 crud方式 基本屬性 static final int default initial capacity 1 4 aka 16 雜湊表中陣列預設初始值大小為16 static final int maxim...
Django xadmin安裝最詳細
django.contrib.admin django.contrib.auth django.contrib.contenttypes django.contrib.sessions django.contrib.messages django.contrib.staticfiles xadmin...
LCS最詳細題解!!!!!
lcs即最長公共子串行問題 解題思路 lcs就是乙個簡單的dp,例子1 字串a abcdef,長度l1.字串b ebacd,長度l2.結果 3 bcd 核心思路 用分割線的方法,一開始分割線在字串a的首字元的右邊,然後內層迴圈去找和首字元相同的字元,如果找到的話就讓當前狀態下 即分割線在首字元右邊 ...