HashMapd的存取原理你知道多少

帥地發表於2018-05-27

HashMapd的存取原理你知道多少


在java的容器集合中,hashmap的使用頻率可以說是相當高的。不過對於hashmap的存(put())以及取(get())的原理可能很多人還不大清楚,今天,我就給大家介紹下它是如何存如何取的

HashMapd的存取原理你知道多少

#下面以回答問題的形式來講解#

**假如有面試官問你,hashmap是如何存資料的,你會怎麼回答? **

  1. 我想每個人都知道hashmap是以鍵值對的方式來存資料的,有些人可能會這麼回答:當我們執行put(key, value)函式的時候,以key作為鍵,value作為值來存,並且如果key相同的話,則新的value會覆蓋掉舊的value

  2. 而有些人可能會這麼回答:hashmap在存資料的時候是基於hashing的原理,當我們呼叫put(key,value)方法的時候,其實我們會先對鍵key呼叫key.hashcode()方法,根據方法返回的hashcode來找到bucket的位置來存Entry物件。(Entry物件存有key和value)。如下圖:(這裡沒有考慮碰撞)

HashMapd的存取原理你知道多少

顯然前者和後者的回答,後者的回答還是相對好點的。不過,這可能僅僅只是故事的開始。


**這時面試官可能會問你,如果兩個key物件的hashcode相同怎麼辦? **

  1. 對於不熟悉hashcode()和equals()這兩個方法的人來說,他可能會直接說,因為hashcode相同,那麼兩個物件是同一個物件,進而新的value覆蓋掉舊的value。如果你這樣回答,後果你懂 。(當然可能面試會提醒你或直接問你別的問題了)。

  2. 有些人則會回答,由於hashcode相同,那麼它們對應的bucket顯然也是相同的,這個時候就會產生所謂的碰撞(hashmap的底層儲存結構是 陣列+連結串列)。每個bucket索引對應一個連結串列,這個時候系統就會找到對應的連結串列,並在連結串列的尾部加上這個Entry物件,如下圖:(圖畫的有點醜,哈哈)

HashMapd的存取原理你知道多少

  1. 這個時候跑出來個第三者,自豪著補充了一句:根據hashcode找到對應的bucket之後,還會在對應的連結串列逐一檢查這個連結串列裡有沒存在相同的key物件,這個時候是通過equals這個方法來對比的。如果有,者用新的value取代舊的value。如果沒有,則向樓上說的,在連結串列的尾部加上這個新的Entry物件。

  • 這個時候,hashmap的put原理講解就告一段落了。下面說說獲取get(key)原理
  • 其實get原理和put原理是差不多的,一個逆向的過程。
  1. 當我們呼叫get(key)的時候,會呼叫key的hashcode方法獲得hashcode.
  2. 根據hashcode獲取相應的bucket。
  3. 由於一個bucket對應的連結串列中可能存有多個Entry,這個時候會呼叫key的equals方法來找到對應的Entry
  4. 最後把值返回(這句好像是廢話....但我還是想說下)。

繼續漲知識......

和其他容器一樣,當我們沒有指定大小直接new一個hashmap的時候

HashMapd的存取原理你知道多少

系統會自動給我們初始化一個數值。如果我們在存資料的過程中,大小超過了負載因子定義的容量怎麼辦?

  • 這裡先給大家解釋下 負載因子:負載因子(load factor,假設大小為n)就是當一個map填滿了n倍的bucket的時候,hashmap就會進行擴容。

  • 其實當一個map被填滿到75%的時候(預設的負載因子大小是0.75),它就會進行擴容,建立一個大小是原理兩倍的bucket陣列,並且將原理的資料存放到新的陣列裡。


大家都知道,當Map在擴容新的陣列並且移動資料的時候,都是比較消耗時間和記憶體的,如果我們事先能預測到我們到存的資料的大致大小的話,我們就可以新建立hashmap的時候指定大小,這樣,可以大小減少擴容帶來的消耗。

  • 這裡可能大家有一些疑問,例如為啥預設的負載因子大小是0.75呢(看有些人在討論這個問題)。對於這個我覺得可能是通過大量的資料測出來的(還沒有去百度看別人的解答,僅代表個人觀點,歡迎你們的解答)
  • 這裡在給大家解釋以下負載因子的作用(可能有些人還不知道負載因子的幹啥用的)
  1. 負載因子越大,陣列要被填滿時,元素就會越多,元素越多,衝突的機率就會越大,一個連結串列存的元素也會越多,查詢的時候就會越慢。但是,此時空間的利用率更高了----空間換時間
  2. 負載因此越小,陣列要被填滿時,元素就會越少,衝突也會也少,一個連結串列的元素也會越少,查詢的時候也就越快。但是,空間的利用率低了-----時間換空間。

  • 暫時先講到這裡,大家如果有什麼疑問。歡迎提出

  • 如果有哪裡講錯了,非常歡迎指點出來

  • 如果你覺得有所有所收穫,那就,,,點個讚唄,也希望關注我的公眾號(di201805)勒,我就儘自己的努力來總結學過的知識以及自己的一些感想、看法。

HashMapd的存取原理你知道多少

相關文章