準備 HashMap 的資料結構及儲存原理

2021-08-26 15:03:52 字數 4289 閱讀 5964

hashmap的資料結構

陣列

優點:儲存區間連續,定址容易 ,按下標隨機訪問效率高o(1)

缺點:占用記憶體嚴重,插入刪除困難

鍊錶 優點:儲存位址不連續,可寬展空間,插入,刪除效率高

缺點:訪問效率低 o(n)

雜湊表

綜合了陣列和鍊錶的特性,既定址容易,插入刪除效率又高

問題:什麼是hashmap?為什麼要用到hashmap?

1 .hashmap是基於雜湊表的map介面的非同步實現。hashmap 不保證對映的順序,特別是不能保證順序一致不變。

2 .hashmap 儲存的是鍵值對,可以支援任何型別的作為key 或者 value,並且可以儲存null鍵和 null 值,hashmap資料儲存很快,插入刪除效率高。

public

class

hashmap

extends

abstractmap

implements

map, cloneable, serializable

hashmap 是雜湊法(hashing)或者 雜湊法的原理,通過put(key, value) 儲存鍵值對物件到 hashmap中, 通過 get(key) 從 hashmap 中獲取物件。當通過 put(key , value) 方法傳遞 key 和 value 時,首先 呼叫 key.hashcode() , 通過返回的 hashcode 來找到 bucket 位置來儲存 entry(鍵值對)物件。需要說明一點,hashmap 是在bucket 中儲存 鍵值對 物件,即 map.entry.

hashmap 可以看成乙個大的陣列,然後每個陣列元素的型別是node 型別,node型別有兩個子類,treenode 和 entry ,如果是鍊錶即使 node類,紅黑樹 是 treenode 類

public v put(k key, v value) 

static final int hash(object key)

final v putval(int hash, k key, v value, boolean onlyifabsent,

boolean evict)

if (e.hash == hash &&

((k = e.key) == key || (key != null && key.equals(k))))

break;

p = e;}}

v oldvalue = e.value;

if (!onlyifabsent || oldvalue == null)

e.value = value;

afternodeaccess(e);

return oldvalue;}}

++modcount;

if (++size > threshold)

resize();

afternodeinsertion(evict);

return

null;

}

我們看到在 put(key, value) 方法裡呼叫了 hash(key) 方法,來得到該 key 的 hashcode. hash(key)方法主要目的是使得高低bit 位參與到hash 計算中,從而減少 hash 衝突。

在 putvalue() 函式插入資料方法時,會判斷節點是鍊錶還是紅黑樹,分別對不同的賦值方法,如果單個bucket 的節點數量大於 8 個,會把鍊錶轉化成紅黑樹。

public v get(object key) 

final nodegetnode(int hash, object key) while ((e = e.next) != null);}}

return

null;

}

get方法 也呼叫了 hash(key) 方法來獲取 hashcode。

接著呼叫 getnode(hash, key) 查詢符合條件的結點

問題:hashmap 的工作原理你了解麼?

答:hashmap 是雜湊法(hashing 或者 雜湊法)的原理,通過put(key, value) 儲存物件到 hashmap中, 通過 get(key) 從 hashmap 中獲取物件。當通過 put(key , value) 方法傳遞 key 和 value 時,首先 呼叫 key.hashcode() , 通過返回的 hashcode 來找到 bucket 位置 來儲存 entry (鍵值對)物件。需要說明一點,hashmap 是在bucket 中儲存 鍵值對 物件,即 map.entry.

問題:hashmap 的put() ,get() 方法工作原理?

或者 hashmap 的訪問過程是什麼?

答:

put 方法的過程:

put(key, value) 是把鍵值對 物件儲存到 hashmap 中。

首先獲取到 key後,通過hash函式 (hash(key)),獲取到 key 的 hashcode (int hash = key.hashcode()),這個值是乙個固定的int 型別的值。

其次 通過hashcode 獲取到 bucket 位置(陣列下標 index = hash % entry.length ,hashcode值對bucket數求模)來儲存 entry 物件。

get方法過程:

首先獲取key 後,通過hash函式 (hash(key)),獲取到 key 的 hashcode (int hash = key.hashcode()),這個值是乙個固定的int 型別的值。

其次 通過hashcode 獲取到 bucket 位置(陣列下標 index = hash % entry.length ,hashcode值對bucket數求模)

最後 遍歷linkedlist ,呼叫keys.equals()方法 在linkedlist找到正確的節點,進而找到正確的值物件。

問題:

1 如果兩個 key 的 hashcode 相同會發生什麼?

2 如何獲取 value 物件 ?

答:

1 如果兩個 key物件 的 hashcode 相同時,它們的 bucket 也相同,會發上碰撞問題,使用linkedlist 解決碰撞問題,將鍵值對 物件儲存在 linkedlist 的下乙個結點中。

2 獲取 value 物件的時候,會呼叫get() 方法,接著會呼叫hash函式 獲取鍵物件的 hashcode,找到bucke位置,接著遍歷 linkedlist ,通過keys. equals() 方法,找到 linkedlist 中的正確結點。最終找到 value 物件。

儲存方式問題:

在hashmap 中存放一系列鍵值對,其中 key 為某個自定義的型別,放入hashmap 後,在外部把乙個 key 屬性進行修改, 然後在用這個 key 從 hashmap 裡取出元素, 這個時候 hashmap 會返回什麼?

答:返回 null

第一次儲存的時候,首先獲取到 key後,通過hash函式 (hash(key)),獲取到 key 的 hashcode (int hash = key.hashcode()),這個值是乙個固定的int 型別的值。

其次 通過hashcode 獲取到 bucket 位置(陣列下標 index = hash % entry.length ,hashcode值對bucket數求模)來儲存 entry 物件。

當我們去獲取元素的時候,key.hashcode 已經發生變化,所以這裡hash函式結果也發生了變化,所以當用這個key 獲得hashcode去需要 bucket 的儲存位置是乙個錯誤的位置,無法找到目標元素。

結論:當我們把鍵值對 物件儲存到hashmap中後,不要去修改 key 的屬性

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

答:雜湊表的預設負載因子是0.75,如果map填滿75%的bucket時,必須調整backet的大小,建立原來hashmap大小的兩倍的bucket陣列,並將原來的物件放入新的bucket陣列中。這個過程叫作rehashing.當容量已經達到最大可能值時,那麼該方法就將容量調整到integer.max_value返回,這時,需要建立一張新錶,將原表的對映到新錶中。

hashMap的資料結構

在jdk8中,hashmap是用了陣列和鍊錶以及紅黑樹這三種資料結構 首先,在hashmap類中,都有乙個table陣列,我們在儲存資料時,對這個資料的hash值進行一系列的計算 計算出它在table中的位置 下標 並將它存放進去 然而,我們在hashmap是什麼 中提到,不同的物件的hash值可能...

hash map的資料結構剖析及相關方法

hash map是個很有用的索引結構,對於大規模資料檢索的時候,用處大大的。本文基於原始碼的基礎上,從資料結構開始剖析,進而介紹一些常用的方法。hash map是基於hash table基礎上封裝的方法類,下面看看hash table的資料結構 template,class equalkey equ...

關於HashMap的資料結構

一hashmap的資料結構 jdk1.8以前是陣列 鍊錶 jdk1.8以後是陣列 鍊錶 紅黑色 二資料結構的物理結構 是指資料的邏輯結構在計算機中的儲存形式 資料元素的儲存結構形式有如下兩種 兩種結構,各有優點和缺點,可以相互結合的運用 hashmap正好兩種資料結構都用到了 三陣列 hashmap...