Java——HashMap

Java中HashMap的工作原理:

一院促,存儲方式: Java中的HashMap是以鍵值對(key-value)的形式存儲元素的吨拍。

二防症,調(diào)用原理: HashMap需要一個hash函數(shù)溅漾,它使用hashCode()和equals()方法來向集合/從集合添加和檢索元素。當調(diào)用put()方法的時候计露,HashMap會計算key的hash值博脑,然后把鍵值對存儲在集合中合適的索引上。如果key已經(jīng)存在了票罐,value會被更新成新值叉趣。

三,其他熱性: HashMap的一些重要的特性是它的容量(capacity)该押,負載因子(load factor)和擴容極限(threshold resizing)疗杉。

一、Java中的hashCode和equals:

1蚕礼、關于hashCode

hashCode的存在主要是用于查找的快捷性烟具,如Hashtable,HashMap等奠蹬,hashCode是用來在散列存儲結(jié)構(gòu)中確定對象的存儲地址的

如果兩個對象相同朝聋,就是適用于equals(java.lang.Object) 方法,那么這兩個對象的hashCode一定要相同

如果對象的equals方法被重寫罩润,那么對象的hashCode也盡量重寫,并且產(chǎn)生hashCode使用的對象翼馆,一定要和equals方法中使用的一致割以,否則就會違反上面提到的第2點

兩個對象的hashCode相同金度,并不一定表示兩個對象就相同,也就是不一定適用于equals(java.lang.Object) 方法严沥,只能夠說明這兩個對象在散列存儲結(jié)構(gòu)中猜极,如Hashtable,他們“存放在同一個籃子里“

再歸納一下就是hashCode是用于查找使用的消玄,而equals是用于比較兩個對象的是否相等的跟伏。

2、關于equals

1.equals和==

==用于比較引用和比較基本數(shù)據(jù)類型時具有不同的功能:

比較基本數(shù)據(jù)類型翩瓜,如果兩個值相同受扳,則結(jié)果為true

而在比較引用時,如果引用指向內(nèi)存中的同一對象兔跌,結(jié)果為true;

equals()作為方法勘高,實現(xiàn)對象的比較。由于==運算符不允許我們進行覆蓋坟桅,也就是說它限制了我們的表達华望。因此我們復寫equals()方法,達到比較對象內(nèi)容是否相同的目的仅乓。而這些通過==運算符是做不到的赖舟。

2.object類的equals()方法的比較規(guī)則為:如果兩個對象的類型一致,并且內(nèi)容一致夸楣,則返回true,這些類有:

java.io.file,java.util.Date,java.lang.string,包裝類(Integer,Double等)

String s1=new String("abc");

String s2=new String("abc");

System.out.println(s1==s2);

System.out.println(s1.equals(s2));

運行結(jié)果為false true


Java中HashMap的實現(xiàn)原理:

1.??? HashMap概述

??? HashMap是基于哈希表的Map接口的非同步實現(xiàn)宾抓。此實現(xiàn)提供所有可選的映射操作,并允許使用null值和null鍵裕偿。此類不保證映射的順序洞慎,特別是它不保證該順序恒久不變。

??? 在java編程語言中嘿棘,最基本的結(jié)構(gòu)就是兩種劲腿,一個是數(shù)組,另外一個是模擬指針(引用)鸟妙,所有的數(shù)據(jù)結(jié)構(gòu)都可以用這兩個基本結(jié)構(gòu)來構(gòu)造的焦人,HashMap也不例外。HashMap實際上是一個“鏈表散列”的數(shù)據(jù)結(jié)構(gòu)重父,即數(shù)組和鏈表的結(jié)合體花椭。



圖中可以看出以上圖片HashMap底層就是一個數(shù)組結(jié)構(gòu),數(shù)組中的每一項又是一個鏈表房午。當新建一個HashMap的時候矿辽,就會初始化一個數(shù)組。

Java源碼:

可以看出,Entry就是數(shù)組中的元素袋倔,每個 Map.Entry 其實就是一個key-value對雕蔽,它持有一個指向下一個元素的引用,這就構(gòu)成了鏈表宾娜。

2批狐、HashMap實現(xiàn)存儲和讀取:

(1)存儲:


根據(jù)hash值得到這個元素在數(shù)組中的位置 即下標前塔,如果數(shù)組該位置上已經(jīng)存放有其他元素了嚣艇,那么在這個位置上的元素將以鏈表的形式存放,新加入的放在鏈頭华弓,最先加入的放在鏈尾食零。如果數(shù)組該位置上沒有元素,就直接將該元素放到此數(shù)組中的該位置上该抒。

(2)讀然藕椤:


從HashMap中get元素時,首先計算key的hashCode凑保,找到數(shù)組中對應位置的某一元素冈爹,然后通過key的equals方法在對應位置的鏈表中找到需要的元素。

(3)總結(jié):

HashMap 在底層將 key-value 當成一個整體進行處理欧引,這個整體就是一個 Entry 對象频伤。HashMap 底層采用一個 Entry[ ] 數(shù)組來保存所有的 key-value 對,當需要存儲一個 Entry 對象時芝此,會根據(jù)hash算法來決定其在數(shù)組中的存儲位置憋肖,在根據(jù)equals方法決定其在該數(shù)組位置上的鏈表中的存儲位置;當需要取出一個Entry時婚苹,也會根據(jù)hash算法找到其在數(shù)組中的存儲位置岸更,再根據(jù)equals方法從該位置上的鏈表中取出該Entry。

3膊升、HashMap的resize:

?當hashmap中的元素越來越多的時候怎炊,碰撞的幾率也就越來越高? 因為數(shù)組的長度是固定的,所以為了提高查詢的效率廓译,就要對hashmap的數(shù)組進行擴容评肆,數(shù)組擴容這個操作也會出現(xiàn)在ArrayList中,所以這是一個通用的操作非区,很多人對它的性能表示過懷疑瓜挽,不過想想我們的“均攤”原理,就釋然了征绸,而在hashmap數(shù)組擴容之后久橙,最消耗性能的點就出現(xiàn)了:原數(shù)組中的數(shù)據(jù)必須重新計算其在新數(shù)組中的位置俄占,并放進去,這就是resize淆衷。

?????? 那么hashmap什么時候進行擴容呢颠放?當hashmap中的元素個數(shù)超過數(shù)組大小*loadFactor時,就會進行數(shù)組擴容吭敢,loadFactor的默認值為0.75,也就是說暮芭,默認情況下鹿驼,數(shù)組大小為16,那么當hashmap中元素個數(shù)超過16*0.75=12的時候辕宏,就把數(shù)組的大小擴展為2*16=32畜晰,即擴大一倍,然后重新計算每個元素在數(shù)組中的位置瑞筐,而這是一個非常消耗性能的操作凄鼻,所以如果我們已經(jīng)預知hashmap中元素的個數(shù),那么預設元素的個數(shù)能夠有效的提高hashmap的性能聚假。比如說块蚌,我們有1000個元素new HashMap(1000), 但是理論上來講new HashMap(1024)更合適,不過上面annegu已經(jīng)說過膘格,即使是1000峭范,hashmap也自動會將其設置為1024。 但是new HashMap(1024)還不是更合適的瘪贱,因為0.75*1000 < 1000, 也就是說為了讓0.75 * size > 1000, 我們必須這樣new HashMap(2048)才最合適纱控,既考慮了&的問題,也避免了resize的問題菜秦。

總結(jié):HashMap的實現(xiàn)原理:

利用key的hashCode重新hash計算出當前對象的元素在數(shù)組中的下標

存儲時甜害,如果出現(xiàn)hash值相同的key,此時有兩種情況球昨。(1)如果key相同尔店,則覆蓋原始值;(2)如果key不同(出現(xiàn)沖突)褪尝,則將當前的key-value放入鏈表中

獲取時闹获,直接找到hash值對應的下標,在進一步判斷key是否相同河哑,從而找到對應值避诽。

理解了以上過程就不難明白HashMap是如何解決hash沖突的問題,核心就是使用了數(shù)組的存儲方式璃谨,然后將沖突的key的對象放入鏈表中沙庐,一旦發(fā)現(xiàn)沖突就在鏈表中做進一步的對比鲤妥。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市拱雏,隨后出現(xiàn)的幾起案子棉安,更是在濱河造成了極大的恐慌,老刑警劉巖铸抑,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贡耽,死亡現(xiàn)場離奇詭異,居然都是意外死亡鹊汛,警方通過查閱死者的電腦和手機蒲赂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來刁憋,“玉大人滥嘴,你說我怎么就攤上這事≈脸埽” “怎么了若皱?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長尘颓。 經(jīng)常有香客問我走触,道長,這世上最難降的妖魔是什么疤苹? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任饺汹,我火速辦了婚禮,結(jié)果婚禮上痰催,老公的妹妹穿的比我還像新娘兜辞。我一直安慰自己,他們只是感情好夸溶,可當我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布逸吵。 她就那樣靜靜地躺著,像睡著了一般缝裁。 火紅的嫁衣襯著肌膚如雪扫皱。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天捷绑,我揣著相機與錄音韩脑,去河邊找鬼。 笑死粹污,一個胖子當著我的面吹牛段多,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播壮吩,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼进苍,長吁一口氣:“原來是場噩夢啊……” “哼加缘!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起觉啊,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤拣宏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后杠人,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體勋乾,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年嗡善,在試婚紗的時候發(fā)現(xiàn)自己被綠了市俊。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡滤奈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出撩满,到底是詐尸還是另有隱情蜒程,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布伺帘,位于F島的核電站昭躺,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏伪嫁。R本人自食惡果不足惜领炫,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望张咳。 院中可真熱鬧帝洪,春花似錦、人聲如沸脚猾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽龙助。三九已至砰奕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間提鸟,已是汗流浹背军援。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留称勋,地道東北人胸哥。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像赡鲜,于是被迫代替她去往敵國和親烘嘱。 傳聞我的和親對象是個殘疾皇子昆禽,可洞房花燭夜當晚...
    茶點故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內(nèi)容