HASHMAP(JDK1.7)最詳細(xì)原理分析(二)

昨天的博客我解釋了HASHMAP(JDK1.7)在PUT的時(shí)候會(huì)發(fā)生沖突,而解決沖突的方式就是使用鏈表,那么我們假設(shè)HASHMAP存儲(chǔ)結(jié)構(gòu)如下圖:

那么節(jié)點(diǎn)1和節(jié)點(diǎn)2組成了一個(gè)鏈表,那么現(xiàn)在如果再來(lái)PUT一個(gè)節(jié)點(diǎn)3,假設(shè)節(jié)點(diǎn)3也需要插在這個(gè)鏈表中,我們考慮鏈表的插入效率,將節(jié)點(diǎn)3插在鏈表的頭部是最快的,那么就會(huì)如下圖:

那么按照上圖這種插入辦法,會(huì)出現(xiàn)一個(gè)問(wèn)題:

當(dāng)我們需要get(節(jié)點(diǎn)2)時(shí),我們先將節(jié)點(diǎn)2的key進(jìn)行哈希然后算出下標(biāo),拿到下標(biāo)后可以定位到數(shù)組中的節(jié)點(diǎn)1,但是發(fā)現(xiàn)節(jié)點(diǎn)1不等于節(jié)點(diǎn)2,所以不是最終的結(jié)果,但是節(jié)點(diǎn)1存在下一個(gè)節(jié)點(diǎn),所以可以順著向下的指針找到節(jié)點(diǎn)2。

那么當(dāng)我們需要get(節(jié)點(diǎn)3)時(shí)呢,我們發(fā)現(xiàn)是找不到節(jié)點(diǎn)3的,所以當(dāng)我們把節(jié)點(diǎn)簡(jiǎn)單的插在鏈表的頭部是不行的。

那HashMap是怎么實(shí)現(xiàn)的呢?HashMap確實(shí)是將節(jié)點(diǎn)插在鏈表的頭部,但是在插完之后HashMap會(huì)將整個(gè)鏈表向下移動(dòng)一位,移動(dòng)完之后就會(huì)變成:

那么現(xiàn)在PUT的時(shí)候插入一個(gè)元素的思路就是:將新節(jié)點(diǎn)插在鏈表的頭部,此時(shí)新節(jié)點(diǎn)就是當(dāng)前這個(gè)鏈表的頭節(jié)點(diǎn),接下來(lái)把頭節(jié)點(diǎn)移動(dòng)到數(shù)組位置即可。

當(dāng)我們?cè)谑褂肏ashMap的時(shí)候,還可能會(huì)出現(xiàn)下面的使用方式:

HashMap<String,String>hashMap=newHashMap<>();
hashMap.put("1","2");
Stringvalue=hashMap.put("1","3");
System.out.println(value);

第三行代碼也是PUT,而這個(gè)時(shí)候在HashMap里會(huì)將value覆蓋,也就是key="1"對(duì)應(yīng)的value最終為"3",而第三行代碼返回的value將會(huì)是2。

我們現(xiàn)在來(lái)考慮這個(gè)PUT它是如何實(shí)現(xiàn)的,其實(shí)很簡(jiǎn)單,第三行代碼的邏輯也是先對(duì)"1"計(jì)算哈希值以及對(duì)應(yīng)的數(shù)組下標(biāo),有了數(shù)組下標(biāo)之后就可以找到對(duì)應(yīng)的位置的鏈表,而在將新節(jié)點(diǎn)插入到鏈表之前,還需要判斷一下當(dāng)前新節(jié)點(diǎn)的key值是不是已經(jīng)在這個(gè)鏈表上存在,所以需要先去遍歷當(dāng)前這個(gè)位置的鏈表,在遍歷的過(guò)程中如果找到了相同的key則會(huì)進(jìn)行value的覆蓋,并且返回oldvalue。

好,寫(xiě)到這里其實(shí)對(duì)于HashMap的PUT的主要邏輯也差不多了,總結(jié)一下:

PUT(key,value)

int hashcode = key.hashCode();

int index = hashcode & (數(shù)組長(zhǎng)度-1)

遍歷index位置的鏈表,如果存在相同的key,則進(jìn)行value覆蓋,并且返回之前的value值

將key,value封裝為節(jié)點(diǎn)對(duì)象(Entry)

將節(jié)點(diǎn)插在index位置上的鏈表的頭部

將鏈表頭節(jié)點(diǎn)移動(dòng)到數(shù)組上

這是最核心的7步,然后在這個(gè)過(guò)程中還有很重要的一步就是擴(kuò)容,而擴(kuò)容是發(fā)生在插入節(jié)點(diǎn)之前的,也就是步驟4和5之間的。

那么關(guān)于JDK1.7里HashMap的擴(kuò)容時(shí)會(huì)出現(xiàn)“死鎖”問(wèn)題的,我們下篇文章繼續(xù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容