資料結構 HashMap原理解析

2021-09-25 11:11:54 字數 2860 閱讀 5367

hashing(雜湊法或雜湊法)的概念

雜湊法(hashing)是一種將字元組成的字串轉換為固定長度(一般是更短長度)的數值或索引值的方法,稱為雜湊法,也叫雜湊法。由於通過更短的雜湊值比用原始值進行資料庫搜尋更快,這種方法一般用來在資料庫中建立索引並進行搜尋,同時還用在各種解密演算法中。

hashmap概念和底層結構

hashmap是基於雜湊表的map介面的非同步實現。此實現提供所有可選的對映操作,並允許使用null值和null鍵。hashmap儲存的是鍵值對,hashmap很快。此類不保證對映的順序,特別是它不保證該順序恆久不變。

hashmap實際上是乙個「鍊錶雜湊」的資料結構,即陣列和鍊錶的結合體。

陣列:儲存區間連續,占用記憶體嚴重,定址容易,插入刪除困難; 

鍊錶:儲存區間離散,占用記憶體比較寬鬆,定址困難,插入刪除容易; 

hashmap綜合應用了這兩種資料結構,實現了定址容易,插入刪除也容易。

hashmap的結構示意圖如下:

hashmap的基本儲存原理以及儲存內容的組成

基本原理:先宣告乙個下標範圍比較大的陣列來儲存元素。另外設計乙個雜湊函式(也叫做雜湊函式)來獲得每乙個元素的key(關鍵字)的函式值(即陣列下標,hash值)相對應,陣列儲存的元素是乙個entry類,這個類有三個資料域,key、value(鍵值對),next(指向下乙個entry)。

例如, 第乙個鍵值對a進來。通過計算其key的hash得到的index=0。記做:entry[0] = a。 

第二個鍵值對b,通過計算其index也等於0, hashmap會將b.next =a,entry[0] =b, 

第三個鍵值對 c,index也等於0,那麼c.next = b,entry[0] = c;這樣我們發現index=0的地方事實上訪問了a,b,c三個鍵值對,它們通過next這個屬性鏈結在一起。我們可以將這個地方稱為桶。 對於不同的元素,可能計算出了相同的函式值,這樣就產生了「衝突」,這就需要解決衝突,「直接定址」與「解決衝突」是雜湊表的兩大特點。

hashmap的工作原理以及訪問方法過程

hashmap的工作原理 :hashmap是基於雜湊法(又稱雜湊法hashing)的原理,使用put(key, value)儲存物件到hashmap中,使用get(key)從hashmap中獲取物件。當我們給put()方法傳遞鍵和值時,我們先對鍵呼叫hashcode()方法,返回的hashcode用於找到bucket(桶)位置來儲存entry物件。」hashmap是在bucket中儲存鍵物件和值物件,作為map.entry。並不是僅僅只在bucket中儲存值。

hashmap具體的訪問過程如下: 

put鍵值對的方法的過程是:

①判斷鍵值對陣列table[i]是否為空或為null,否則執行resize()進行擴容;

②根據鍵值key計算hash值得到插入的陣列索引i,如果table[i]==null,直接新建節點新增,轉向⑥,如果table[i]不為空,轉向③;

③判斷table[i]的首個元素是否和key一樣,如果相同直接覆蓋value,否則轉向④,這裡的相同指的是hashcode以及equals;

④判斷table[i] 是否為treenode,即table[i] 是否是紅黑樹,如果是紅黑樹,則直接在樹中插入鍵值對,否則轉向⑤;

⑤遍歷table[i],判斷鍊錶長度是否大於8,大於8的話把鍊錶轉換為紅黑樹,在紅黑樹中執行插入操作,否則進行鍊錶的插入操作;遍歷過程中若發現key已經存在直接覆蓋value即可;

⑥插入成功後,判斷實際存在的鍵值對數量size是否超多了最大容量threshold,如果超過,進行擴容。

get值方法的過程是:

1、指定key 通過hash函式得到key的hash值 

int hash=key.hashcode();

2、呼叫內部方法 getnode(),得到桶號(一般都為hash值對桶數求模) 

int index =hash%entry.length;

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

4、如果得到 key 所在的桶的頭結點恰好是紅黑樹節點,就呼叫紅黑樹節點的 gettreenode() 方法,否則就遍歷鍊錶節點。gettreenode 方法使通過呼叫樹形節點的 find()方法進行查詢。由於之前新增時已經保證這個樹是有序的,因此查詢時基本就是折半查詢,效率很高。

5、如果對比節點的雜湊值和要查詢的雜湊值相等,就會判斷 key 是否相等,相等就直接返回;不相等就從子樹中遞迴查詢。

hashmap中直接位址用hash函式生成;解決衝突,用比較函式解決。如果每個桶內部只有乙個元素,那麼查詢的時候只有一次比較。當許多桶內沒有值時,許多查詢就會更快了(指查不到的時候)。

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

如何重新調整hashmap的大小

「如果hashmap的大小超過了負載因子(load factor)定義的容量,怎麼辦?」

預設的負載因子大小為0.75,也就是說,當乙個map填滿了75%的bucket時候,和其它集合類(如arraylist等)一樣,將會建立原來hashmap大小的兩倍的bucket陣列,來重新調整map的大小,並將原來的物件放入新的bucket陣列中。這個過程叫作rehashing,因為它呼叫hash方法找到新的bucket位置。

HashMap原理解析

日常工作中經常用到map,基本上是用map map new hashmap 來得到乙個hashmap物件,之前並未深入去研究hashmap的實現原理,只是去簡單的去建立然後使用它。這次想深入了解便,去研究了一下hashmap的原始碼。做點筆記,記錄一下自己的一些收穫,想到哪寫到哪吧。hashmap繼...

HashMap原理解析

hashmap在jdk1.8之前和jdk1.8之後內部實現有所不同 在jdk1.8之前,hashmap底層是陣列和鍊錶的結構,從jdk1.8開始內部實現使用了陣列和鍊錶以及紅黑樹一 jdk1.8之前的hashmap實現原理 以jdk1.7為例 先看構造方法 public hashmap public...

HashMap的原理解析

進行hashmap原理解析 手寫乙個簡單的hashmap hashmap的底層執行是陣列加鍊表 鍊錶就是為了解決雜湊碰撞的情況 public class hashmap 關羽的hash值是 679082 index is 2 孫權的hash值是 751370 index is 5 張飛的hash值是...