資料結構中實現資料儲存的方式主要有:陣列和鍊錶 陣列
陣列儲存區間是連續的,占用記憶體嚴重,故空間複雜的很大。但陣列的二分查詢時間複雜度小,為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...