Java基礎-理解散列與散列碼

1.從HashMap說起

我們知道Map以鍵值對的形式來存儲數據。有一點值得說明的是,如果要使用我們自己的類作爲鍵,我們必須同時重寫hashCode() 和 equals()兩個方法。HashMap使用equals方法來判斷當前的鍵是否與表中的鍵相同。equals()方法需要滿足以下5個條件

  • 自反性 x.equals(x) 一定返回true
  • 對稱性 x.equals(y)返回true,則y.equals(x) 也返回true
  • 傳遞性 x.equals(y)返回true,y.equals(z)返回true,則x.equals(y)返回true
  • 一致性 如果對象中的信息沒有改變,x.equals(y)要麼一直返回true,要麼一直返回false
  • 對任何不是null的x,想x.equals(null)一定返回false

2.散列

散列的價值在於速度。

假如鍵沒有按照一定的順序進行保存,那麼查詢的時候就只能按照順序進行線性查詢,然而,線性查詢是最慢的查詢方式。所以,將鍵值按照一定的順序排序,並且使用二分查找能購有效的提升速度。散列在此之上,更近一步,他將鍵保存在數組中(數組的查詢速度最快),用數組來表示鍵的信息,但是由於Map的容量是可變的,而數組的容量是不變的。要解決這個問題,數組中存的並不是鍵本身,而是鍵對象生成的一個數字,將其作爲數組的下標,這個數字就是散列碼。

而這種辦法所產生的問題就是下標重複。而我們的解決辦法就是配合equals來確定鍵值。

查詢的過程首先就是計算散列碼,然後用散列碼來查詢函數(下標),通常,我們的數組中保存的是值的list,因此,我們計算出散列碼之後,通過下表取到的對應部分的list,然後通過equals就可以快速找到鍵值。

3.HashCode

hashCode函數是用來生成散列碼的,我們看看Integer的計算方式(ps:我們自己的對象我們要選擇自己的方式)

    public static int hashCode(int value) {
        return value;
    }

這裏不在多說,我們自己的類有自己的散列碼實現就好。

4. 以HashMap的get方法來說明

    public V get(Object key) {
        if (key == null) {
            HashMapEntry<K, V> e = entryForNullKey;
            return e == null ? null : e.value;
        }

        int hash = Collections.secondaryHash(key);
        HashMapEntry<K, V>[] tab = table;
        for (HashMapEntry<K, V> e = tab[hash & (tab.length - 1)];
                e != null; e = e.next) {
            K eKey = e.key;
            if (eKey == key || (e.hash == hash && key.equals(eKey))) {
                return e.value;
            }
        }
        return null;
    }
  • int hash = Collections.secondaryHash(key); 計算出散列碼
  • HashMapEntry
            K eKey = e.key;
            if (eKey == key || (e.hash == hash && key.equals(eKey))) {
                return e.value;
            }
  • 若地址相同,返回值,
  • 若hash值相等且equals返回true,返回值

5.總結

不知道各位朋友看了這篇之後是否理解了散列和散列碼。還是原來就懂,被我這麼一頓bb,不懂了!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章