HashMapd的存取原理你知道多少



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

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

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

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


**這時面試官可能會問你,若是兩個key對象的hashcode相同怎麼辦? **cdn

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

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

  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. 負載所以越小,數組要被填滿時,元素就會越少,衝突也會也少,一個鏈表的元素也會越少,查詢的時候也就越快。可是,空間的利用率低了-----時間換空間。

  • 暫時先講到這裏,你們若是有什麼疑問。歡迎提出

  • 若是有哪裏講錯了,很是歡迎指點出來

  • 若是你以爲有全部所收穫,那就,,,點個讚唄,也但願關注個人公衆號(di201805)勒,我就盡本身的努力來總結學過的知識以及本身的一些感想、見解。

相關文章
相關標籤/搜索