面试高频问题:HashMap实现原理
2019獨角獸企業(yè)重金招聘Python工程師標準>>>
今天給同學(xué)們講講一個面試經(jīng)常遇到的高頻問題,HashMap實現(xiàn)原理,希望在金三銀四的季節(jié)對同學(xué)們有幫助。
HashMap結(jié)構(gòu)圖目錄
?一、嘮叨
?二、解析思路
?三、get方法
?四、put方法
?五、resize方法
?一、嘮叨
認真閱讀了下HashMap的實現(xiàn)方式,也參考了網(wǎng)上別人的一些解析,個人覺得還是有些東西想說。網(wǎng)上有的文章名字為HashMap源碼解析,實際上就是給它里面的一些方法加上一些注釋而已,有不少都是這樣的。
我自己看源碼的時候,發(fā)現(xiàn)不是別人不想解析,而是它的實現(xiàn)真的需要親自研讀,多理順幾遍才知道怎么回事。
我在這里解析的文字描述也較多,不管誰的解析,自己也都要看一下JDK源碼的具體實現(xiàn),我們僅提供參考而已。
二、解析思路
源碼不太方便看,先說明一下我的閱讀思路。
1.把常用的幾個方法拷貝到文本編輯器里面。
2.HashMap中不同的時候會有不同的流程,梳理方法中的邏輯流程。就像采用極端法,采用特殊的數(shù)據(jù),然后查看方法執(zhí)行語句。未執(zhí)行的語句暫時不考慮。
3.注釋源碼...我覺得HashMap的實現(xiàn)方式不夠好,關(guān)鍵的幾個方法里面包含的情況太多了,閱讀起來是有難度的,而寫程序的目的之一不就是讓其他開發(fā)者閱讀嗎?一個方法內(nèi)部做了太多的事情,違反了代碼整潔的規(guī)則,一個函數(shù)做要盡量少的事情。
解析
之前稍微介紹了一些HashMap的特性,HashMap初探。
(https://www.jianshu.com/p/be9ffb76db30)這里接著深入。
三、get方法
先挑最簡單的說
?
?
1 先從數(shù)組下標,找到對應(yīng)的Node2.?
2 如果Node里的第一個節(jié)點命中,直接返回
3 如果有沖突,則通過key.equals(k)去查找對應(yīng)的entry
4 若為樹,則在樹中通過key.equals(k)查找,O(logn);
5 若為鏈表,則在鏈表中通過key.equals(k)查找,O(n)。put方法這個中間涉及的邏輯多一些,方法需要分不同的步驟看。
?
?
四、put方法
這個中間涉及的邏輯多一些,方法需要分不同的步驟看。
思路:
1對key的hashCode()做hash,然后再計算index;
2如果沒碰撞直接放到bucket里;
3如果碰撞了,以鏈表的形式存在buckets后;
4如果節(jié)點已經(jīng)存在就替換old 5value(保證key的唯一性)
6如果碰撞導(dǎo)致鏈表過長(大于等于TREEIFY_THRESHOLD),就把鏈表轉(zhuǎn)換成紅黑樹;
7如果Node的容量滿了(超過load factor*current capacity),就要resize。
?
一般不發(fā)生碰撞的時候,相對簡單,數(shù)據(jù)量較小的情況下。
?
?
我解釋下關(guān)于碰撞沖的循環(huán)。
1.查看是否存在相同的key,存在相同的key跳出循環(huán),覆蓋key的value。
2.如果不存在相同的key,在鏈表末尾插入新的Node如果鏈表節(jié)點過長,轉(zhuǎn)換為樹。
3.如果鏈表節(jié)點過長,轉(zhuǎn)換為樹。
?
?
紅黑樹的部分,我們下次單獨解析
?五、resize方法
這個涉及的內(nèi)容,有不少線需要捋一捋。首先看申明時候會resize()。它們都在調(diào)用put的時候執(zhí)行的。
1.table == 的時候
?
?
2.鍵值映射的的數(shù)目大于臨界值的時候。
?
?
六、resize具體方法
?
?
如果是第一次resize,我們抽出來會執(zhí)行到的語句。
1.初始化容量
2.初始化threshold,也就是初始化臨界值,決定了table的鍵值對數(shù)目到什么時候會再次resize()
?
第二次及后續(xù)的resize執(zhí)行流程
?
?
resize中對有碰撞的鏈表的操作寫的很有意思,再敘述一下。在重新分配索引的時候,有重新組建鏈表的操作。
舉個比較夸張的例子,讀者就明白了。
1.e.hash < 2,那么e.hash&oldCap就等于0,索引為小于之前hash表大小以內(nèi)的索引。也就是當(dāng)初的索引不變。
2.e.hash > 2的時候,e.hash&old不等于0,那么它的索引就為當(dāng)前表的索引再加上新擴容的大小。
? ? ? ? ? ? ? ? 案例圖
這個圖說的是,當(dāng)hashmap的表大小為2擴充到4的時候,原本掛載在1位置的鏈表,重新分配之后的樣子。
最后
篇幅有限,我這里僅僅介紹了get方法,put方法,resize方法的具體原理,文章就已經(jīng)非常長了,不利于閱讀。
下次再補充一下HashMap的hash方法原理,其余的相關(guān)注意事項。
轉(zhuǎn)載于:https://my.oschina.net/u/4118408/blog/3054746
總結(jié)
以上是生活随笔為你收集整理的面试高频问题:HashMap实现原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (十四)java版spring clou
- 下一篇: 微服务中集成分布式配置中心 Apollo