面試高頻問題:HashMap實現原理

今天給同窗們講講一個面試常常遇到的高頻問題,HashMap實現原理,但願在金三銀四的季節對同窗們有幫助。面試

HashMap結構圖目錄數組

1、嘮叨

2、解析思路

3、get方法

4、put方法

##5、resize方法編輯器

1、嘮叨

認真閱讀了下HashMap的實現方式,也參考了網上別人的一些解析,我的以爲仍是有些東西想說。網上有的文章名字爲HashMap源碼解析,實際上就是給它裏面的一些方法加上一些註釋而已,有很多都是這樣的。 我本身看源碼的時候,發現不是別人不想解析,而是它的實現真的須要親自研讀,多理順幾遍才知道怎麼回事。 我在這裏解析的文字描述也較多,無論誰的解析,本身也都要看一下JDK源碼的具體實現,咱們僅提供參考而已。函數

##2、解析思路 源碼不太方便看,先說明一下個人閱讀思路。 1.把經常使用的幾個方法拷貝到文本編輯器裏面。 2.HashMap中不一樣的時候會有不一樣的流程,梳理方法中的邏輯流程。就像採用極端法,採用特殊的數據,而後查看方法執行語句。未執行的語句暫時不考慮。 3.註釋源碼...我以爲HashMap的實現方式不夠好,關鍵的幾個方法裏面包含的狀況太多了,閱讀起來是有難度的,而寫程序的目的之一不就是讓其餘開發者閱讀嗎?一個方法內部作了太多的事情,違反了代碼整潔的規則,一個函數作要儘可能少的事情。 解析 以前稍微介紹了一些HashMap的特性,HashMap初探。 (www.jianshu.com/p/be9ffb76d…cdn

##3、get方法 先挑最簡單的說blog

1 先從數組下標,找到對應的Node2. 2 若是Node裏的第一個節點命中,直接返回 3 若是有衝突,則經過key.equals(k)去查找對應的entry 4 若爲樹,則在樹中經過key.equals(k)查找,O(logn); 5 若爲鏈表,則在鏈表中經過key.equals(k)查找,O(n)。put方法這個中間涉及的邏輯多一些,方法須要分不一樣的步驟看。索引

##4、put方法 這個中間涉及的邏輯多一些,方法須要分不一樣的步驟看。 思路: 1對key的hashCode()作hash,而後再計算index; 2若是沒碰撞直接放到bucket裏; 3若是碰撞了,以鏈表的形式存在buckets後; 4若是節點已經存在就替換old 5value(保證key的惟一性) 6若是碰撞致使鏈表過長(大於等於TREEIFY_THRESHOLD),就把鏈表轉換成紅黑樹; 7若是Node的容量滿了(超過load factor*current capacity),就要resize。ci

通常不發生碰撞的時候,相對簡單,數據量較小的狀況下。開發

我解釋下關於碰撞衝的循環。 1.查看是否存在相同的key,存在相同的key跳出循環,覆蓋key的value。 2.若是不存在相同的key,在鏈表末尾插入新的Node若是鏈表節點過長,轉換爲樹。 3.若是鏈表節點過長,轉換爲樹。get

紅黑樹的部分,咱們下次單獨解析

5、resize方法

這個涉及的內容,有很多線須要捋一捋。首先看申明時候會resize()。它們都在調用put的時候執行的。

1.table == 的時候

2.鍵值映射的的數目大於臨界值的時候。

6、resize具體方法

若是是第一次resize,咱們抽出來會執行到的語句。 1.初始化容量 2.初始化threshold,也就是初始化臨界值,決定了table的鍵值對數目到何時會再次resize()

第二次及後續的resize執行流程

resize中對有碰撞的鏈表的操做寫的頗有意思,再敘述一下。在從新分配索引的時候,有從新組建鏈表的操做。

舉個比較誇張的例子,讀者就明白了。 1.e.hash < 2,那麼e.hash&oldCap就等於0,索引爲小於以前hash表大小之內的索引。也就是當初的索引不變。 2.e.hash > 2的時候,e.hash&old不等於0,那麼它的索引就爲當前表的索引再加上新擴容的大小。

案例圖

這個圖說的是,當hashmap的表大小爲2擴充到4的時候,本來掛載在1位置的鏈表,從新分配以後的樣子。

最後 篇幅有限,我這裏僅僅介紹了get方法,put方法,resize方法的具體原理,文章就已經很是長了,不利於閱讀。 下次再補充一下HashMap的hash方法原理,其他的相關注意事項。

相關文章
相關標籤/搜索