HashMap和TreeMap的內部結構

2022-09-06 23:33:21 字數 2793 閱讀 1438

1、基於雜湊表的 map 介面的實現。此實現提供所有可選的對映操作,並允許使用 null 值和 null 鍵。(除了非同步和允許使用 null 之外,hashmap 類與 hashtable 大致相同。)此類不保證對映的順序,特別是它不保證該順序恆久不變。

2、hashmap 的例項有兩個引數影響其效能:初始容量 和載入因子。容量是雜湊表中桶的數量,初始容量只是雜湊表在建立時的容量。載入因子是雜湊表在其容量自動增加之前可以達到多滿的一種尺度。當雜湊表中的條目數超出了載入因子與當前容量的乘積時,則要對該雜湊表進行rehash 操作(即重建內部資料結構),從而雜湊表將具有大約兩倍的桶數。

按照key關鍵字的雜湊值和buckets陣列的長度取模查詢桶的位置,如果key的雜湊值相同,hash衝突(也就是指向了同乙個桶)則每次新新增的作為頭節點,而最先新增的在表尾。

hashmap中的桶的個數就是下圖中的0- n的陣列的長度,儲存第乙個entry的位置叫『桶(bucket)』而桶中只能存乙個值也就是鍊錶的頭節點,鍊錶的每個節點就是新增的乙個值(hashmap內部類entry的例項entry有哪些屬性之後在詳說),也可以這樣理解,乙個entry 型別的儲存鍊錶的陣列。陣列的索引位置就是乙個個桶的索引位址。

從上圖我們可以發現雜湊表是由陣列+鍊錶組成的,乙個長度為16的陣列中,每個元素儲存的是乙個鍊錶的頭結點。那麼這些元素是按照什麼樣的規則儲存到陣列中呢。一般情況是通過hash(key)%len獲得,也就是元素的key的雜湊值對陣列長度取模得到。比如上述雜湊表中,12%16=12,28%16=12,108%16=12,140%16=12。所以12、28、108以及140都儲存在陣列下標為12的位置。

1、hashmap 是鏈式陣列(儲存鍊錶的陣列)實現查詢速度可以,而且能快速的獲取key對應的value;

2、查詢速度的影響因素有 容量和負載因子,容量大負載因子小查詢速度快但浪費空間,反之則相反;

3、陣列的index值是(key 關鍵字, hashcode為key的雜湊值, len 陣列的大小):hashcode%len的值來確定,如果容量大負載因子小則index相同(index相同也就是指向了同乙個桶)的概率小,鍊錶長度小則查詢速度快,反之index相同的概率大煉表比較長查詢速度慢。

4、對於hashmap以及其子類來說,他們是採用hash演算法來決定集合中元素的儲存位置,當初始化hashmap的時候系統會建立乙個長度為capacity的entry陣列,這個陣列裡可以儲存元素的位置稱為桶(bucket),每乙個桶都有其指定索引,系統可以根據索引快速訪問該桶中儲存的元素。

5、無論何時hashmap 中的每個桶都只儲存乙個元素(entry 物件)。由於entry物件可以包含乙個引用變數用於指向下乙個entry,因此可能出現hashmap 的桶(bucket)中只有乙個entry,但這個entry指向另乙個entry 這樣就形成了乙個entry 鏈。

6、通過上面的原始碼發現hashmap在底層將key_value對當成乙個整體進行處理(entry 物件)這個整體就是乙個entry物件,當系統決定儲存hashmap中的key_value對時,完全沒有考慮entry中的value,而僅僅是根據key的hash值來決定每個entry的儲存位置。

jdk1.8中使用乙個node陣列來儲存資料,但這個node可能是鍊錶結構,也可能是紅黑樹結構如果插入的key的hashcode相同,那麼這些key也會被定位到node陣列的同乙個格仔裡。

如果同乙個格仔裡的key不超過8個,使用鍊錶結構儲存。如果超過了8個,那麼會呼叫treeifybin函式,將鍊錶轉換為紅黑樹。那麼即使hashcode完全相同,由於紅黑樹的特點,查詢某個特定元素,也只需要o(log n)的開銷

也就是說put/get的操作的時間複雜度最差只有o(log n)。

需要注意:key的物件,必須正確的實現了compare介面

紅黑樹是一種近似平衡的二叉查詢樹,它能夠確保任何乙個節點的左右子樹的高度差不會超過二者中較低那個的一陪。具體來說,紅黑樹是滿足如下條件的二叉查詢樹(binary search tree):

每個節點要麼是紅色,要麼是黑色。

根節點必須是黑色

紅色節點不能連續(也即是,紅色節點的孩子和父親都不能是紅色)。

對於每個節點,從該點至null(樹尾端)的任何路徑,都含有相同個數的黑色節點。

在樹的結構發生改變時(插入或者刪除操作),往往會破壞上述條件3或條件4,需要通過調整使得查詢樹重新滿足紅黑樹的條件。

2、treemap的底層使用了紅黑樹來實現,像treemap物件中放入乙個key-value 鍵值對時,就會生成乙個entry物件,這個物件就是紅黑樹的乙個節點,其實這個和hashmap是一樣的,乙個entry物件作為乙個節點,只是這些節點存放的方式不同。

3、存放每乙個entry物件時都會按照key鍵的大小按照二叉樹的規範進行存放,所以treemap中的資料是按照key從小到大排序的。

treemap總結:

程式新增新節點時,總是從樹的根節點開始比較,即將根節點當成當前節點。如果新增節點大於當前節點並且當前節點的右節點存在,則以右節點作為當前節點,如果新增節點小於當前節點並且當前節點的左子節點存在,則以左子節點作為當前節點;如果新增節點等於當前節點,則用新增節點覆蓋當前節點,並結束迴圈 直到某個節點的左右子節點不存在,將新節點新增為該節點的子節點。如果新節點比該節點大,則新增其為右子節點。如果新節點比該節點小,則新增其為左子節點;

TreeMap和HashMap的問題

在一次面試的過程中,有乙個問題 hashmap存放資料是無序的,如何編寫程式,使資料先進先出。當時我沒做出來,但是我回來折騰了半天,就寫了下面的成序。首先思考hashmap通過hashcode對其內容進行快速查詢,而treemap中所有的元素都保持著某種固定的順序,然後在google下,通過改變ke...

treemap 和 hashmap的效率比較

區別 1,hashmap是無序的,treemap是有序的,整個key是按照自然順序來的。2,hashmap可以put乙個null當key treemap卻不支援。3,底層結構不一樣,乙個是陣列 紅黑樹,乙個直接就是紅黑樹。但是hashmap是最最最常用的map集合,不考慮順序的時候,他是首選,假如你...

HashMap 和 TreeMap 的內部結構

1 基於雜湊表的 map 介面的實現。此實現提供所有可選的對映操作,並允許使用 null 值和 null 鍵。除了非同步和允許使用 null 之外,hashmap 類與 hashtable 大致相同。此類不保證對映的順序,特別是它不保證該順序恆久不變。2 hashmap 的例項有兩個引數影響其效能 ...