HashMapd的存取原理你知道多少


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

 

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

**假如有面試官問你,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)。如下圖:(這里沒有考慮碰撞)

 

 

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


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

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

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

 

 

  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的時候

 

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

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

  • 其實當一個map被填滿到75%的時候(默認的負載因子大小是0.75),它就會進行擴容,創建一個大小是原理兩倍的bucket數組,並且將原理的數據存放到新的數組里。


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

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

如果你習慣在微信公眾號看技術文章
想要獲取更多資源的同學
歡迎關注我的公眾號:苦逼的碼農
每天向你推送 各種視頻資源,電子書、 技術文章以及
和面試有關的 算法專題 每日一題


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM