java 小知識點HashMap

2021-07-10 04:18:34 字數 2990 閱讀 7358

hashmap是乙個「鍊錶雜湊」的資料結構,是陣列和鍊錶的結合體。

從上圖中可以看出,hashmap底層就是乙個陣列結構,陣列中的每一項又是乙個鍊錶。當新建乙個hashmap的時候,就會初始化乙個陣列。

put操作

public v put(k key, v value) 

}// 如果i索引處的entry為null,表明此處還沒有entry。

modcount++;

// 將key、value新增到i索引處。

addentry(hash, key, value, i);

return

null;

}

從上面的源**中可以看出:當我們往hashmap中put元素的時候,先根據key的hashcode重新計算hash值,根據hash值得到這個元素在陣列中的位置(即下標),如果陣列該位置上已經存放有其他元素了,那麼在這個位置上的元素將以鍊錶的形式存放,新加入的放在鏈頭,最先加入的放在鏈尾。如果陣列該位置上沒有元素,就直接將該元素放到此陣列中的該位置上。

addentry(hash, key, value, i)方法根據計算出的hash值,將key-value對放在陣列table的i索引處。addentry 是 hashmap 提供的乙個包訪問許可權的方法,**如下:

void addentry(int hash, k key, v value, int bucketindex)
當系統決定儲存hashmap中的key-value對時,完全沒有考慮entry中的value,僅僅只是根據key來計算並決定每個entry的儲存位置。我們完全可以把 map 集合中的 value 當成 key 的附屬,當系統決定了 key 的儲存位置之後,value 隨之儲存在那裡即可。

hash(int h)方法根據key的hashcode重新計算一次雜湊。此演算法加入了高位計算,防止低位不變,高位變化時,造成的hash衝突。

static

int hash(int h)

我們可以看到在hashmap中要找到某個元素,需要根據key的hash值來求得對應陣列中的位置。如何計算這個位置就是hash演算法。前面說過hashmap的資料結構是陣列和鍊錶的結合,所以我們當然希望這個hashmap裡面的 元素位置盡量的分布均勻些,盡量使得每個位置上的元素數量只有乙個,那麼當我們用hash演算法求得這個位置的時候,馬上就可以知道對應位置的元素就是我們要的,而不用再去遍歷鍊錶,這樣就大大優化了查詢的效率。

對於任意給定的物件,只要它的 hashcode() 返回值相同,那麼程式呼叫 hash(int h) 方法所計算得到的 hash 碼值總是相同的。

讀取

public v get(object key) 

return

null;

}

有了上面儲存時的hash演算法作為基礎,理解起來這段**就很容易了。從上面的源**中可以看出:從hashmap中get元素時,首先計算key的hashcode,找到陣列中對應位置的某一元素,然後通過key的equals方法在對應位置的鍊錶中找到需要的元素。

歸納歸納起來簡單地說,hashmap 在底層將 key-value 當成乙個整體進行處理,這個整體就是乙個 entry 物件。hashmap 底層採用乙個 entry 陣列來儲存所有的 key-value 對,當需要儲存乙個 entry 物件時,會根據hash演算法來決定其在陣列中的儲存位置,在根據equals方法決定其在該陣列位置上的鍊錶中的儲存位置;當需要取出乙個entry時,也會根據hash演算法找到其在陣列中的儲存位置,再根據equals方法從該位置上的鍊錶中取出該entry。

hashmap的resize(rehash):

當hashmap中的元素越來越多的時候,hash衝突的機率也就越來越高,因為陣列的長度是固定的。所以為了提高查詢的效率,就要對hashmap的陣列進行擴容,陣列擴容這個操作也會出現在arraylist中,這是乙個常用的操作,而在hashmap陣列擴容之後,最消耗效能的點就出現了:原陣列中的資料必須重新計算其在新陣列中的位置,並放進去,這就是resize。

那麼hashmap什麼時候進行擴容呢?當hashmap中的元素個數超過陣列大小*loadfactor時,就會進行陣列擴容,loadfactor的預設值為0.75,這是乙個折中的取值。也就是說,預設情況下,陣列大小為16,那麼當hashmap中元素個數超過16*0.75=12的時候,就把陣列的大小擴充套件為 2*16=32,即擴大一倍,然後重新計算每個元素在陣列中的位置,而這是乙個非常消耗效能的操作,所以如果我們已經預知hashmap中元素的個數,那麼預設元素的個數能夠有效的提高hashmap的效能。

hashmap的效能引數:

hashmap 包含如下幾個構造器:

hashmap():構建乙個初始容量為 16,負載因子為 0.75 的 hashmap。

hashmap(int initialcapacity):構建乙個初始容量為 initialcapacity,負載因子為 0.75 的 hashmap。

hashmap(int initialcapacity, float loadfactor):以指定初始容量、指定的負載因子建立乙個 hashmap。

hashmap的基礎構造器hashmap(int initialcapacity, float loadfactor)帶有兩個引數,它們是初始容量initialcapacity和載入因子loadfactor。

initialcapacity:hashmap的最大容量,即為底層陣列的長度。

loadfactor:負載因子loadfactor定義為:雜湊表的實際元素數目(n)/ 雜湊表的容量(m)。

負載因子衡量的是乙個雜湊表的空間的使用程度,負載因子越大表示雜湊表的裝填程度越高,反之愈小。對於使用鍊錶法的雜湊表來說,查詢乙個元素的平均時間是o(1+a),因此如果負載因子越大,對空間的利用更充分,然而後果是查詢效率的降低;如果負載因子太小,那麼雜湊表的資料將過於稀疏,對空間造成嚴重浪費。

Java 」繼承「小知識點

public class test class aclass class bclass extends aclass void printval 中父類宣告的變數儲存的是子類變數的引用。牢記,當其呼叫被子類重寫的方法時,其呼叫的是子類的方法 當其呼叫與子類同名的成員時,其呼叫的仍是父類中的成員。另一...

java基礎之HashMap相關知識點

1.hashmap是一種由陣列和鍊錶構成的資料結構,用於儲存 key value對 元素,同時繼承了陣列的查詢優點和鍊錶的修改優點。2.hashmap是非同步的,所以速度很快。並且鍵和值可以為null。3.hashmap使用put key,value 方法儲存物件到hashmap中,使用get ke...

hashmap知識點小結

1.hashmap是基於hash表的map介面實現 2.hashmap底層採用的是entry陣列和鍊錶實現的 3.hashmap採用鍵值隊 key,value 結構,其中 key不可重複,可以為null,value的值可以重複。4.hashmap為執行緒不安全,無synchronized修飾 5.h...