hashmap的資料結構
陣列優點:儲存區間連續,定址容易 ,按下標隨機訪問效率高o(1)
缺點:占用記憶體嚴重,插入刪除困難
鍊錶 優點:儲存位址不連續,可寬展空間,插入,刪除效率高
缺點:訪問效率低 o(n)
雜湊表
綜合了陣列和鍊錶的特性,既定址容易,插入刪除效率又高
問題:什麼是hashmap?為什麼要用到hashmap?1 .hashmap是基於雜湊表的map介面的非同步實現。hashmap 不保證對映的順序,特別是不能保證順序一致不變。2 .hashmap 儲存的是鍵值對,可以支援任何型別的作為key 或者 value,並且可以儲存null鍵和 null 值,hashmap資料儲存很快,插入刪除效率高。
hashmap 是雜湊法(hashing)或者 雜湊法的原理,通過put(key, value) 儲存鍵值對物件到 hashmap中, 通過 get(key) 從 hashmap 中獲取物件。當通過 put(key , value) 方法傳遞 key 和 value 時,首先 呼叫 key.hashcode() , 通過返回的 hashcode 來找到 bucket 位置來儲存 entry(鍵值對)物件。需要說明一點,hashmap 是在bucket 中儲存 鍵值對 物件,即 map.entry.public
class
hashmap
extends
abstractmap
implements
map, cloneable, serializable
hashmap 可以看成乙個大的陣列,然後每個陣列元素的型別是node 型別,node型別有兩個子類,treenode 和 entry ,如果是鍊錶即使 node類,紅黑樹 是 treenode 類
我們看到在 put(key, value) 方法裡呼叫了 hash(key) 方法,來得到該 key 的 hashcode. hash(key)方法主要目的是使得高低bit 位參與到hash 計算中,從而減少 hash 衝突。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;
}
在 putvalue() 函式插入資料方法時,會判斷節點是鍊錶還是紅黑樹,分別對不同的賦值方法,如果單個bucket 的節點數量大於 8 個,會把鍊錶轉化成紅黑樹。
get方法 也呼叫了 hash(key) 方法來獲取 hashcode。public v get(object key)
final nodegetnode(int hash, object key) while ((e = e.next) != null);}}
return
null;
}
接著呼叫 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 物件。
儲存方式問題:答:返回 null在hashmap 中存放一系列鍵值對,其中 key 為某個自定義的型別,放入hashmap 後,在外部把乙個 key 屬性進行修改, 然後在用這個 key 從 hashmap 裡取出元素, 這個時候 hashmap 會返回什麼?
第一次儲存的時候,首先獲取到 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...