更新時間:2020-04-30 14:07:13 來源:動力節(jié)點 瀏覽4587次
一、HashMap基礎(chǔ)
基本定義:根據(jù)源代碼的描述可知,HashMap是基于哈希表的Map接口的實現(xiàn),其包含了Map接口的所有映射操作,并且允許使用null鍵和null值。
與HashTable的區(qū)別:HashMap可以近似地看成是HashTable,但是它是非線程安全的,并且允許使用null鍵和null值,而這些都與HashTable恰巧相反。
注:HashMap可以使用ConcurrentHashMap代替,ConcurrentHashMap是一個線程安全,更加快速的HashMap。
存儲結(jié)構(gòu):HashMap的存儲結(jié)構(gòu)其實就是哈希表的存儲結(jié)構(gòu)(由數(shù)組與鏈表結(jié)合組成,稱為鏈表的數(shù)組)。如下圖所示:

/**
*Thetable,initializedonfirstuse,andresizedas
*necessary.Whenallocated,lengthisalwaysapoweroftwo.
*(Wealsotoleratelengthzeroinsomeoperationstoallow
*bootstrappingmechanicsthatarecurrentlynotneeded.)
*/
transientNode
staticclassNode
finalinthash;
finalKkey;
Vvalue;
Node
...
}
HashMap的主干是一個Entry數(shù)組。Entry是HashMap的基本組成單元,每一個Entry包含一個key-value鍵值對。
如上圖所示,HashMap中元素存儲的形式是鍵-值對(key-value對,即Entry對),所有具有相同hashcode值的鍵(key)所對應(yīng)的entry對會被鏈接起來組成一條鏈表,而數(shù)組的作用則是存儲鏈表中第一個結(jié)點的地址值。
二、影響HashMap性能的因素
在HashMap中,還存在著兩個概念,桶(buckets)和加載因子(loadfactor)。
桶(buckets):上圖中的標(biāo)有0、1、2、3、….、11所對應(yīng)的數(shù)組空間就是一個個桶。
加載因子(loadfactor):是哈希表在其容量自動增加之前可以達到多滿的一種尺度,默認值是0.75。
根據(jù)源代碼中所述,影響HashMap性能有兩個因素:哈希表中的初始化容量(桶的數(shù)量)和加載因子。當(dāng)哈希表中條目數(shù)超過了當(dāng)前容量與加載因子的乘積時,哈希表將會作出自我調(diào)整,將容量擴充為原來的兩倍,并且重新將原有的元素重新映射到表中,這一過程成為rehash??吹竭@里,相必大家會發(fā)現(xiàn)rehash操作是會造成時間與空間的開銷的,因此為什么初始化容量與加載因子會影響HashMap的性能也就可以理解了。
三、put/get方法實現(xiàn)原理
put操作:HashMap在進行put操作的時候,會首先調(diào)用Key值中的hashCode()方法,用于獲取對應(yīng)的bucket的下標(biāo)值以便存放數(shù)據(jù)。
HashMap通過key值的hashCode獲得了對應(yīng)的bucket存儲空間的下標(biāo),然后進入bucket空間,通過鏈表遍歷的方式逐個查詢,看看鏈表中是否已經(jīng)存在了這個key的鍵-值對,如果已經(jīng)存在則用新值替換舊值,否則插入新的鍵-值對。
看到這里,相信大家會發(fā)現(xiàn),hashCode值相同的兩個值可能是不同的兩個對象,而當(dāng)put進去的是另一個hashCode值相等的對象時,會發(fā)生沖突,而在HashMap中解決這種沖突的方法就是將hashCode值相同的key值所對應(yīng)的key-value對串聯(lián)成一條鏈表,請見上面的HashMap數(shù)據(jù)結(jié)構(gòu)圖。
get操作:HashMap在進行g(shù)et操作的時候,與put方法類似,會首先調(diào)用Key值中的hashCode()方法,用于獲取對應(yīng)的bucket的下標(biāo)值,找到bucket的位置后,再通過key.equals()方法找到對應(yīng)的鍵-值對,從而獲得對應(yīng)的value值。
總結(jié)
HashMap是基于hashing原理對key-value對進行存儲與獲取,當(dāng)使用put()方法添加key-value對時,它會首先檢查hashCode的值,并以此獲得對應(yīng)的bucket位置進行存儲,當(dāng)發(fā)生沖突時(hashCode值相同的兩個不同key),新的key-value對會以結(jié)點的形式添加到鏈表的末尾(先看看鏈表中是否已經(jīng)存在了這個key,如果已經(jīng)存在,則更新;否則就添加到鏈表的末尾)。而使用get()方法時,同樣地會根據(jù)key的hashCode值找到相應(yīng)的bucket位置,再通過key.equals()方法找到對應(yīng)的key-value對,最終成功獲取value值。

以上就是動力節(jié)點java培訓(xùn)機構(gòu)的小編針對“Java基礎(chǔ)學(xué)習(xí):hashmap定義”的內(nèi)容進行的回答,希望對大家有所幫助,如有疑問,請在線咨詢,有專業(yè)老師隨時為你服務(wù)。
相關(guān)閱讀