1. 程式人生 > >Java基礎-理解雜湊與雜湊碼

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,不懂了!!!