欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

HashMap原理的深入理解

 更新時(shí)間:2019年04月03日 09:53:34   作者:visant  
這篇文章主要介紹了對(duì)HashMap原理的理解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

hashing(散列法或哈希法)的概念

散列法(Hashing)是一種將字符組成的字符串轉(zhuǎn)換為固定長(zhǎng)度(一般是更短長(zhǎng)度)的數(shù)值或索引值的方法,稱為散列法,也叫哈希法。由于通過(guò)更短的哈希值比用原始值進(jìn)行數(shù)據(jù)庫(kù)搜索更快,這種方法一般用來(lái)在數(shù)據(jù)庫(kù)中建立索引并進(jìn)行搜索,同時(shí)還用在各種解密算法中。

HashMap概念和底層結(jié)構(gòu)

HashMap是基于哈希表的Map接口的非同步實(shí)現(xiàn)。此實(shí)現(xiàn)提供所有可選的映射操作,并允許使用null值和null鍵。HashMap儲(chǔ)存的是鍵值對(duì),HashMap很快。此類不保證映射的順序,特別是它不保證該順序恒久不變。

HashMap實(shí)際上是一個(gè)“鏈表散列”的數(shù)據(jù)結(jié)構(gòu),即數(shù)組和鏈表的結(jié)合體。

數(shù)組:存儲(chǔ)區(qū)間連續(xù),占用內(nèi)存嚴(yán)重,尋址容易,插入刪除困難;
鏈表:存儲(chǔ)區(qū)間離散,占用內(nèi)存比較寬松,尋址困難,插入刪除容易;
Hashmap綜合應(yīng)用了這兩種數(shù)據(jù)結(jié)構(gòu),實(shí)現(xiàn)了尋址容易,插入刪除也容易。

hashMap的結(jié)構(gòu)示意圖如下:

HashMap的基本存儲(chǔ)原理以及存儲(chǔ)內(nèi)容的組成

基本原理:先聲明一個(gè)下標(biāo)范圍比較大的數(shù)組來(lái)存儲(chǔ)元素。另外設(shè)計(jì)一個(gè)哈希函數(shù)(也叫做散列函數(shù))來(lái)獲得每一個(gè)元素的Key(關(guān)鍵字)的函數(shù)值(即數(shù)組下標(biāo),hash值)相對(duì)應(yīng),數(shù)組存儲(chǔ)的元素是一個(gè)Entry類,這個(gè)類有三個(gè)數(shù)據(jù)域,key、value(鍵值對(duì)),next(指向下一個(gè)Entry)。

例如, 第一個(gè)鍵值對(duì)A進(jìn)來(lái)。通過(guò)計(jì)算其key的hash得到的index=0。記做:Entry[0] = A。
第二個(gè)鍵值對(duì)B,通過(guò)計(jì)算其index也等于0, HashMap會(huì)將B.next =A,Entry[0] =B,
第三個(gè)鍵值對(duì) C,index也等于0,那么C.next = B,Entry[0] = C;這樣我們發(fā)現(xiàn)index=0的地方事實(shí)上存取了A,B,C三個(gè)鍵值對(duì),它們通過(guò)next這個(gè)屬性鏈接在一起。我們可以將這個(gè)地方稱為桶。 對(duì)于不同的元素,可能計(jì)算出了相同的函數(shù)值,這樣就產(chǎn)生了“沖突”,這就需要解決沖突,“直接定址”與“解決沖突”是哈希表的兩大特點(diǎn)。

HashMap的工作原理以及存取方法過(guò)程

HashMap的工作原理 :HashMap是基于散列法(又稱哈希法hashing)的原理,使用put(key, value)存儲(chǔ)對(duì)象到HashMap中,使用get(key)從HashMap中獲取對(duì)象。當(dāng)我們給put()方法傳遞鍵和值時(shí),我們先對(duì)鍵調(diào)用hashCode()方法,返回的hashCode用于找到bucket(桶)位置來(lái)儲(chǔ)存Entry對(duì)象?!盚ashMap是在bucket中儲(chǔ)存鍵對(duì)象和值對(duì)象,作為Map.Entry。并不是僅僅只在bucket中存儲(chǔ)值。

HashMap具體的存取過(guò)程如下:
put鍵值對(duì)的方法的過(guò)程是:

  1. ①判斷鍵值對(duì)數(shù)組table[i]是否為空或?yàn)閚ull,否則執(zhí)行resize()進(jìn)行擴(kuò)容;
  2. ②根據(jù)鍵值key計(jì)算hash值得到插入的數(shù)組索引i,如果table[i]==null,直接新建節(jié)點(diǎn)添加,轉(zhuǎn)向⑥,如果table[i]不為空,轉(zhuǎn)向③;
  3. ③判斷table[i]的首個(gè)元素是否和key一樣,如果相同直接覆蓋value,否則轉(zhuǎn)向④,這里的相同指的是hashCode以及equals;
  4. ④判斷table[i] 是否為treeNode,即table[i] 是否是紅黑樹(shù),如果是紅黑樹(shù),則直接在樹(shù)中插入鍵值對(duì),否則轉(zhuǎn)向⑤;
  5. ⑤遍歷table[i],判斷鏈表長(zhǎng)度是否大于8,大于8的話把鏈表轉(zhuǎn)換為紅黑樹(shù),在紅黑樹(shù)中執(zhí)行插入操作,否則進(jìn)行鏈表的插入操作;遍歷過(guò)程中若發(fā)現(xiàn)key已經(jīng)存在直接覆蓋value即可;
  6. ⑥插入成功后,判斷實(shí)際存在的鍵值對(duì)數(shù)量size是否超多了最大容量threshold,如果超過(guò),進(jìn)行擴(kuò)容。

get值方法的過(guò)程是:

1、指定key 通過(guò)hash函數(shù)得到key的hash值
int hash=key.hashCode();

2、調(diào)用內(nèi)部方法 getNode(),得到桶號(hào)(一般都為hash值對(duì)桶數(shù)求模)
int index =hash%Entry[].length;

3、比較桶的內(nèi)部元素是否與key相等,若都不相等,則沒(méi)有找到。相等,則取出相等記錄的value。

4、如果得到 key 所在的桶的頭結(jié)點(diǎn)恰好是紅黑樹(shù)節(jié)點(diǎn),就調(diào)用紅黑樹(shù)節(jié)點(diǎn)的 getTreeNode() 方法,否則就遍歷鏈表節(jié)點(diǎn)。getTreeNode 方法使通過(guò)調(diào)用樹(shù)形節(jié)點(diǎn)的 find()方法進(jìn)行查找。由于之前添加時(shí)已經(jīng)保證這個(gè)樹(shù)是有序的,因此查找時(shí)基本就是折半查找,效率很高。

5、如果對(duì)比節(jié)點(diǎn)的哈希值和要查找的哈希值相等,就會(huì)判斷 key 是否相等,相等就直接返回;不相等就從子樹(shù)中遞歸查找。

HashMap中直接地址用hash函數(shù)生成;解決沖突,用比較函數(shù)解決。如果每個(gè)桶內(nèi)部只有一個(gè)元素,那么查找的時(shí)候只有一次比較。當(dāng)許多桶內(nèi)沒(méi)有值時(shí),許多查詢就會(huì)更快了(指查不到的時(shí)候)。

HashMap中的碰撞探測(cè)(collision detection)以及碰撞的解決方法

當(dāng)兩個(gè)對(duì)象的hashcode相同時(shí),它們的bucket位置相同,‘碰撞'會(huì)發(fā)生。因?yàn)镠ashMap使用LinkedList存儲(chǔ)對(duì)象,這個(gè)Entry(包含有鍵值對(duì)的Map.Entry對(duì)象)會(huì)存儲(chǔ)在LinkedList中。這兩個(gè)對(duì)象就算hashcode相同,但是它們可能并不相等。 那如何獲取這兩個(gè)對(duì)象的值呢?當(dāng)我們調(diào)用get()方法,HashMap會(huì)使用鍵對(duì)象的hashcode找到bucket位置,遍歷LinkedList直到找到值對(duì)象。找到bucket位置之后,會(huì)調(diào)用keys.equals()方法去找到LinkedList中正確的節(jié)點(diǎn),最終找到要找的值對(duì)象使用不可變的、聲明作final的對(duì)象,并且采用合適的equals()和hashCode()方法的話,將會(huì)減少碰撞的發(fā)生,提高效率。不可變性使得能夠緩存不同鍵的hashcode,這將提高整個(gè)獲取對(duì)象的速度,使用String,Interger這樣的wrapper類作為鍵是非常好的選擇。

如何重新調(diào)整HashMap的大小

“如果HashMap的大小超過(guò)了負(fù)載因子(load factor)定義的容量,怎么辦?”

默認(rèn)的負(fù)載因子大小為0.75,也就是說(shuō),當(dāng)一個(gè)map填滿了75%的bucket時(shí)候,和其它集合類(如ArrayList等)一樣,將會(huì)創(chuàng)建原來(lái)HashMap大小的兩倍的bucket數(shù)組,來(lái)重新調(diào)整map的大小,并將原來(lái)的對(duì)象放入新的bucket數(shù)組中。這個(gè)過(guò)程叫作rehashing,因?yàn)樗{(diào)用hash方法找到新的bucket位置。

以上所述是小編給大家介紹的HashMap原理的理解詳解整合,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

最新評(píng)論