五 HashMap 索引計算

2022-08-30 10:06:08 字數 868 閱讀 4223

從hashmap原始碼中,可以看到求容器下標值的方法,有兩步,首先通過key值計算hash,然後用hash計算下標:

計算hash:

return (key == null) ? 0 : (h = key.hashcode()) ^ (h >>> 16);

計算下標,其下標值為:(n-1) & hash

n = (tab = resize()).length;

p = tab[i = (n - 1) & hash]
即,是通過key的hash值和容器的大小減1,兩者進行與運算,獲取容器陣列下標。這裡使用與運算,其實蘊含了乙個隱藏條件,即陣列的大小n,必須是2的n次方,否則,計算出來的下標值i是無法覆蓋這個範圍[0, n-1]的。

舉個例子,假設兩種情況,一種容器大小為10,不是2的冪,另外一種容器大小為16,剛好是2的4次方。

則,對於第一種,n-1= 9, 二進位制表示為 1001,任何值與該值進行與運算,都無法改變中間的兩個0,只能改變首尾的兩個1,因此結果範圍就縮小了一倍

而,對於第二種,n-1=15,二進位制表示為 1111,該值與其他值與運算後,可以覆蓋範圍[0, 15],而這個範圍剛好是陣列的大小,因此只要hash值均勻分布,結果也是均勻的。

實際上,只要陣列大小是2的冪,則 (n-1) & hash 的結果等效於: hash % (n-1);即與運算、求餘運算通過這個前提,實現了等效。

而計算機中,與運算和求餘運算,兩個計算的效率肯定是前者更好。因為與運算,是直接對位進行邏輯與操作,屬於cpu的底層支援的基礎邏輯操作,但是求餘運算可不是,應該是需要額外的算術運算單元支援的。可能這就是把陣列大小規定為2的冪的原因之一,提高運算效率。

HashMap中如何計算陣列索引下標?

對於key的hashcode做hash操作,無符號右移16位然後做異或運算。還有平方取中法,偽隨機數法和取餘數法。這三種效率都比較低。而無符號右移16位異或運算效率是最高的。集合中的初始化容量 必須是二的n次冪 預設的初始容量是16 1 4相當於1 2的4次方 1 16 static final i...

索引(五)索引 追補

補充 1.unique 要求列唯一 和 primary key 主鍵唯一 約束均為列或列集合提供了唯一性的保證。primary key 主鍵 擁有自動定義的 unique 約束。並且 每個表可以有多個 unique 約束,但是每個表只能有乙個 primary key 約束。2.其他索引型別 norm...

HashMap五種遍歷的方式

mapmap new hashmap map.put 1 value1 map.put 2 value2 map.put 3 value3 第一種 普遍使用,二次取值 system.out.println 通過map.keyset遍歷key和value for string key map.keys...