作者:小秋? ? ? ? 公眾號:苦逼的碼農(nóng)
在java的容器集合中,hashmap的使用頻率可以說是相當高的馒索。不過對于hashmap的存(put())以及取(get())的原理可能很多人還不大清楚渐白,今天碟婆,我就給大家介紹下它是如何存如何取的过吻。
下面以回答問題的形式來講解
假如有面試官問你进泼,hashmap是如何存數(shù)據(jù),你會怎么回答纤虽?
我想每個人都知道hashmap是以鍵值對的方式來存數(shù)據(jù)的乳绕,有些人可能會這么回答:當我們執(zhí)行put(key, value)函數(shù)的時候,以key作為鍵逼纸,value作為值來存洋措,并且如果key相同的話,則新的value會覆蓋掉舊的value杰刽。
這時面試官可能會問你菠发,如果兩個key對象的hashcode相同怎么辦?
- 對于不熟悉hashcode()和equals()這兩個方法的人來說贺嫂,他可能會直接說滓鸠,因為hashcode相同,那么兩個對象是同一個對象第喳,進而新的value覆蓋掉舊的value糜俗。如果你這樣回答,后果你懂 曲饱。(當然可能面試會提醒你或直接問你別的問題了)悠抹。
- 這個時候跑出來個第三者,自豪著補充了一句:根據(jù)hashcode找到對應的bucket之后扩淀,還會在對應的鏈表逐一檢查這個鏈表里有沒存在相同的key對象楔敌,這個時候是通過equals這個方法來對比的。如果有驻谆,者用新的value取代舊的value梁丘。如果沒有侵浸,則向樓上說的,在鏈表的尾部加上這個新的Entry對象氛谜。
- 這個時候掏觉,hashmap的put原理講解就告一段落了。下面說說獲取get(key)原理
- 其實get原理和put原理是差不多的值漫,一個逆向的過程澳腹。
- 當我們調(diào)用get(key)的時候,會調(diào)用key的hashcode方法獲得hashcode.
- 根據(jù)hashcode獲取相應的bucket杨何。
- 由于一個bucket對應的鏈表中可能存有多個Entry,這個時候會調(diào)用key的equals方法來找到對應的Entry
- 最后把值返回(這句好像是廢話….但我還是想說下)酱塔。
繼續(xù)漲知識……
- 這里先給大家解釋下 負載因子:負載因子(load factor,假設大小為n)就是當一個map填滿了n倍的bucket的時候,hashmap就會進行擴容危虱。
- 其實當一個map被填滿到75%的時候(默認的負載因子大小是0.75)羊娃,它就會進行擴容,創(chuàng)建一個大小是原理兩倍的bucket數(shù)組埃跷,并且將原理的數(shù)據(jù)存放到新的數(shù)組里蕊玷。
大家都知道,當Map在擴容新的數(shù)組并且移動數(shù)據(jù)的時候弥雹,都是比較消耗時間和內(nèi)存的垃帅,如果我們事先能預測到我們到存的數(shù)據(jù)的大致大小的話,我們就可以新創(chuàng)建hashmap的時候指定大小剪勿,這樣贸诚,可以大小減少擴容帶來的消耗。
- 這里可能大家有一些疑問厕吉,例如為啥默認的負載因子大小是0.75呢(看有些人在討論這個問題)酱固。對于這個我覺得可能是通過大量的數(shù)據(jù)測出來的(還沒有去百度看別人的解答,僅代表個人觀點头朱,歡迎你們的解答)
- 這里在給大家解釋以下負載因子的作用(可能有些人還不知道負載因子的干啥用的)
- 負載因子越大媒怯,數(shù)組要被填滿時,元素就會越多髓窜,元素越多扇苞,沖突的幾率就會越大,一個鏈表存的元素也會越多寄纵,查詢的時候就會越慢鳖敷。但是,此時空間的利用率更高了——空間換時間
- 負載因此越小程拭,數(shù)組要被填滿時定踱,元素就會越少,沖突也會也少恃鞋,一個鏈表的元素也會越少崖媚,查詢的時候也就越快亦歉。但是,空間的利用率低了——-時間換空間畅哑。
- 暫時先講到這里肴楷,大家如果有什么疑問。歡迎提出
- 如果有哪里講錯了荠呐,非常歡迎指點出來
?