對HashMap實現原理的理解
阿新 • • 發佈:2018-12-23
綜合這幾天網上查資料以及檢視HashMap的原始碼,談談個人對HashMap底層的理解:
HashMap是一個雜湊集合,其底層是陣列+連結串列結構,主體部分是個長度很長的陣列.
結構 :
主體 : Entry陣列(實際存key,value的物件);
連結串列 : 通過next方法指向連結串列下一個結點
- 為了保證HashMap增刪改查的效率,實質並上不是直接以key例項物件作為標識進行存值和取值,從put方法原始碼可以發現底層是獲取key的hashCode值,經過異或運算和indexFor()方法運算得到的值作為標識,但由於hashCode的值並不唯一,經過運算獲取的值也不能保證唯一(雜湊衝突),所以,經過以上運算得來的數值只能作為陣列的索引,當通過索引定位到這個節點時,在遍歷該連結串列,判斷是否存在相同的key物件,如果存在就用新的value覆蓋舊的value
//HashMap部分原始碼
public V put(K key, V value) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
if (key == null)
return putForNullKey(value);
int hash = hash(key);
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null ; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
final int hash(Object k) {
int h = hashSeed;
if (0 != h && k instanceof String) {
return sun.misc.Hashing.stringHash32((String) k);
}
h ^= k.hashCode();
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
hasCode知識點補充
一、hasCode概念
hashCode是jdk根據物件的地址或者字串或者數字算出來的int型別的數值,物件通過呼叫hashCode()方法返回該物件的雜湊碼值。支援此方法是為了提高雜湊表的效能。
二、作用
對於包含容器型別的程式設計語言來說,基本上都會涉及到hashCode。在Java中也一樣,hashCode方法的主要作用是為了配合基於雜湊的集合(無序集合)一起快速正常執行,使用hashCode的價值在於速度:運用hashCode作為標識使得查詢得以快速進行.
三、使用: 拿String舉例
同一個物件
public void test01(){ String str1 = new String("123"); String str2 = str1; int code1 = str1.hashCode(); int code2 = str2.hashCode(); System.out.println(code1); ----->48690 System.out.println(code2); ----->48690 System.out.println(str1.equals(str2)); ----->true }
不同物件,相同內容
public void test02(){ String str1 = new String("aaa"); String str2 = new String("aaa"); int code1 = str1.hashCode(); int code2 = str2.hashCode(); System.out.println(code1); ----->96321 System.out.println(code2); ----->96321 System.out.println(str1.equals(str2)); ----->true }
- 不同字串物件,相同內容,生成的hashCode相同,明顯String裡面hashCode()方法明顯是根據字串內容生成的
- 想要使hashCode()更實用,它必須速度更快,並且必須有意義,也就是說,它必須基於String物件的內容生成hashCode
- 兩個字串物件用equals()方法比較返回true,因為String類重寫了equals()方法,使得內容相同的兩個字串進行比較會返回true
不同物件,不同內容
public void test03(){ String str1 ="Aa"; String str2 ="BB"; int code1 = str1.hashCode(); int code2 = str2.hashCode(); System.out.println(code1); ---->2112 System.out.println(code2); ---->2112 System.out.println(str1.equals(str2)); ---->false }
- hashCode不必是獨一無二的,更應該關注生成速度,而不是唯一性.