Java集合中HashMap的實現原理

2021-07-08 11:10:51 字數 1786 閱讀 8331

資料結構中實現資料儲存的方式主要有:陣列和鍊錶 陣列

陣列儲存區間是連續的,占用記憶體嚴重,故空間複雜的很大。但陣列的二分查詢時間複雜度小,為o(1);陣列的特點是:定址容易,插入和刪除困難;

2.  鍊錶

鍊錶儲存區間離散,占用記憶體比較寬鬆,故空間複雜度很小,但時間複雜度很大,達o(n)。鍊錶的特點是:定址困難,插入和刪除容易。

3.  雜湊表((hash table

)     

既滿足了資料的查詢方便,同時不占用太多的內容空間,使用也十分方便。

我們可以理解為「鍊錶的陣列」:

hashmap的資料結構:

首先hashmap裡面實現乙個靜態內部類entry,其重要的屬性有key , value, next

,從屬性key,value我們就能很明顯的看出來entry就是hashmap鍵值對實現的乙個基礎bean,

我們上面說到hashmap的基礎就是乙個線性陣列,這個陣列就是entry,map裡面的內容都儲存在entry裡面。

null key總是存放在entry陣列的第乙個元素

hashmap隨機訪問的實現:

// 儲存時:

inthash = key.hashcode(); // 每個key的hashcode是乙個固定的int值

intindex = hash % entry.length;//獲得對應的索引值

entry[index] = value;

// 取值時:

inthash = key.hashcode();

intindex = hash % entry.length;

returnentry[index];

疑問:如果兩個key通過hash%entry.length得到的index相同,會不會有覆蓋的危險?

這裡hashmap裡面用到鏈式資料結構的乙個概念。上面我們提到過entry類裡面有乙個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裡面也包含一些優化方面的實現,這裡也說一下。比如:entry的長度一定後,隨著map裡面資料的越來越長,這樣同乙個index的鏈就會很長,會不會影響效能?hashmap裡面設定乙個因子threshold

,隨著map的size越來越大,entry會以一定的規則加長長度

陣列entry的index的確定:hashcode % table.length取模

hashmap訪問時,都需要計算當前key應該對應entry陣列哪個元素,即計算陣列下標

再雜湊過程:

當雜湊表的容量超過預設容量時,必須調整table的大小。當容量已經達到最大可能值時,那麼該方法就將容量調整到

integer.max_value

返回,這時,需要建立一張新錶,將原表的對映到新錶中。  

java 集合學習之hashMap

1 hashmap類繼承關係 public class hashmapextends abstractmap implements map,cloneable,serializable 存放示意圖 由此可以看出hash值一樣的節點會被存放在同一條鍊錶上,比原始遍歷equals查詢效率高 hash值相...

搞懂JAVA集合類 HashMap 三

hashmap底層是雜湊表實現 格式像陣列鍊錶的組合 hashmap基於雜湊表的 map 介面的實現。此實現提供所有可選的對映操作,並允許使用 null 值和 null 鍵。由於儲存位置由hashcode確定,所以此類不保證對映的順序,因為新插入值特別是它不保證該順序恆久不變。hashmap 的例項...

JAVA集合原始碼分析 HashMap

1 hashmap底層資料結構在1.7之前是陣列 鍊錶而1.8之後是陣列 鍊錶 紅黑樹 2 三個變數 initcapacity 陣列初始容量 loadfactory 載入因子 thresold 3 三個過程 陣列擴容的過程 resize 擴容後原陣列資料轉移到新資料結構的過程 陣列新增元素的過程 p...