1. 程式人生 > >對HashMap實現原理的理解

對HashMap實現原理的理解

綜合這幾天網上查資料以及檢視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不必是獨一無二的,更應該關注生成速度,而不是唯一性.