HashMap為什么面試喜歡問

關鍵字:get,put,紅黑樹,自動擴容,數(shù)組,鏈表


在看完spring之后才知道HashMap使用的有多頻繁,spring兩個特性,面向切面編程,面向內(nèi)存編程(并不,是控制反轉)。

控制反轉就是將類初始化,儲存在內(nèi)存中,以HashMap的形式。

底層原理

hashMap中get是如何實現(xiàn)的?

怎么樣通過get直接找到值?程序運行就3件事,循環(huán)/分叉/按順序,

先猜一下,key應該是有一個單獨存儲的空間,循環(huán)key找到要get的那個key,然后怎么拿到值?(這是MySQL索引的原理,MySQL用到的B+tree也是一種平衡二叉樹)

并不是!key沒有獨立空間。

先計算key的hash


tab[hash]直接拿到HashMap中這個hash下標的值

鏈表就是遍歷所有鍵值對,用==或equals來比對鍵,然后拿值;看上去挺粗暴的。


當然其中還有很多非空,長度的判斷,還有是否紅黑樹的判斷。

一些小問題

數(shù)組是怎么查詢的?

數(shù)組可以隨機訪問,這是數(shù)組的一大特點,它不需要從0數(shù)起;因為數(shù)組是先申請一塊連續(xù)空間(所以數(shù)組定長),所以儲存空間是連續(xù)的,tab[3]就直接訪問第4個值,而不需要遍歷前面的幾個值。

為什么用鏈表?

鏈表可以申請不連續(xù)的空間,通過一個指針按順序將這些空間串起來。數(shù)組是定長的,鏈表不是。鏈表的檢索能力偏弱(只能遍歷),作為彌補,它在動態(tài)調整上會更容易。這也是為什么要用紅黑樹的原因,為了查詢快。

集合也是可變的,為什么不用集合?

ArrayList底層由數(shù)組實現(xiàn);集合中的數(shù)組默認是10的容量,在調用add方法時如果容量已滿,會將數(shù)組的容量擴大1.5倍的容量。

其他的所有儲存方式也只不過是數(shù)組和鏈表的組合和變化。

紅黑樹

hashMap有兩種儲存方式,一種是鏈表,數(shù)據(jù)多了就會轉紅黑樹。

紅黑樹怎么查詢呢?看這個結構就是要做2分查找了,確實數(shù)據(jù)多了比for循環(huán)快很多很多。

這看上去應該是有序的,key是怎么排序的?字符串是通過ASCII碼比較大小。


為什么要叫紅黑?不是為了好看,還是有意義的。為了確保樹的平衡

1.根節(jié)點是黑的。

2.葉子節(jié)點也是黑的(指的是NIL/null)。

3.紅色節(jié)點不能連續(xù),父節(jié)點/子節(jié)點都必須是黑的。

4.從任一節(jié)點到其子樹中每個葉子節(jié)點的路徑都包含相同數(shù)量的黑色節(jié)點。(這個很神奇,數(shù)一下還是真的)

5.新加入到紅黑樹的節(jié)點為紅色節(jié)點。(如果加到紅色節(jié)點下就需要調整了)

每個節(jié)點都只能有兩個子節(jié)點(因為是二叉樹)。

hashMap中put是如何實現(xiàn)的?

先計算key的hash值,找到tab[hash]的值,

鏈表就沒什么好說的,遍歷鏈表,key存在就覆蓋值,不存在就新增;主要說紅黑樹的put。

這個紅黑樹樹的結構要保持平衡(是一種平衡二叉樹),子節(jié)點高度要一致。

所有put還是需要技巧的,不能隨便插入;

如果插入的數(shù)據(jù)導致樹不符合上面的規(guī)則,就會開始變色和旋轉;

直到調整到符合上面的規(guī)則,符合規(guī)則后樹又剛好平衡了。

參考關于紅黑樹(R-B tree)原理,看這篇如何

等我看完算法導論再來自己說說。

自動擴容

什么時候擴容?

負載因子默認是0.75,就是容量達到3/4的時候會擴容。

擴容多少?

擴大一倍。

怎么樣擴容?


原來是新建一個更大的數(shù)組,在轉移過去。同時hash算法也會發(fā)生變化,因為開始只能最大生成15的值,擴容之后可以生成到31。

相關hash算法估計和nginx負載均衡用的hash類似,hash(key)%16,這樣他永遠不會超過16。

怪不得網(wǎng)易的面試官會問我數(shù)組怎么擴容?數(shù)組怎么能擴容,幸好機制的我還是猜到了這個方法。

一些構不成問題的疑問

擴容是只擴容數(shù)組,所以鏈表和紅黑樹里數(shù)據(jù)多少都不會觸發(fā)擴容?

并不!是鍵值對的個數(shù)觸發(fā)的。也就是tab[0]的紅黑樹里有12個數(shù)據(jù),tab數(shù)組其他位置下一個數(shù)據(jù)也沒有,也會觸發(fā)擴容。

這樣的機制下,紅黑樹出現(xiàn)的幾率不高?。。ㄦ湵碇荡笥?個轉紅黑樹,低了還會變回鏈表)

如果紅黑樹里數(shù)據(jù)很多,擴容之后更新hash算法,分散了數(shù)據(jù)后,又達到擴容要求,那就要連續(xù)擴容了?

好像也不會,觸發(fā)擴容的那個值所在的位置一定沒有hash沖突。所以不會連續(xù)觸發(fā)擴容。

考慮到擴容時紅黑樹也要重組,擴容是個比較消耗資源的操作。


hash是什么?

散列,把任意長度的字符經(jīng)過hash算法都能生成相同長度的輸出。hashMap中應該是把key散列成數(shù)字,這樣就可以組成數(shù)組下標。



hashmap和hashtable

//todo

treeMap怎么排序?

//todo

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

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

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