天天看點

hashcode了解

官方文檔定義

hashcode方法傳回該對象的哈希碼值。支援該方法是為哈希表提供一些優點,例如,java.util.Hashtable 提供的哈希表。 hashCode 的正常協定是:   
在 Java 應用程式執行期間,在同一對象上多次調用 hashCode 方法時,必須一緻地傳回相同的整數,前提是對象上 equals 比較中所用的資訊沒有被修改。從某一應用程式的一次執行到同一應用程式的另一次執行,該整數無需保持一緻。   
如果根據 equals(Object) 方法,兩個對象是相等的,那麼在兩個對象中的每個對象上調用 hashCode 方法都必須生成相同的整數結果。   
以下情況不 是必需的:如果根據 equals(java.lang.Object) 方法,兩個對象不相等,那麼在兩個對象中的任一對象上調用 hashCode 方法必定會生成不同的整數結果。但是,程式員應該知道,為不相等的對象生成不同整數結果可以提高哈希表的性能。   
實際上,由 Object 類定義的 hashCode 方法确實會針對不同的對象傳回不同的整數。(這一般是通過将該對象的内部位址轉換成一個整數來實作的,但是 JavaTM 程式設計語言不需要這種實作技巧。)   
當equals方法被重寫時,通常有必要重寫 hashCode 方法,以維護 hashCode 方法的正常協定,該協定聲明相等對象必須具有相等的哈希碼。  
           

從定義來看,總結出幾個要點

  1. hashcode的作用

    hashcode主要是應用在hashtable中的查找以及排序中的,根據我查閱資料猜想 使用hashcode進行和查找可以類比于在set集合中抽象為不同的桶。一個桶表示hashcode相同的對象。查找是先基于hashcode進行比較找到對應的桶。然後在進行equel(Object o)進行比較。

  2. hashcode()和equel(Object o)的差別

    從面向對象的概念來說兩個對象是否相同就是通過equel(Object o)方法進行判斷。

    兩個對象不相同那麼equel(Object o)調用的結果就是false。但是hashcode()傳回的值可能相同。

    如果兩個對象相同那麼equel(Object o)調用的結果就是true,hashcode()傳回的值一定相同。

    是以就算重寫equel和hashcode方法也需要滿足這兩個定義

    以下貼出一個小例子

public class HashTest {
    private int i;

    public int getI() {
        return i;
    }

    public void setI(int i) {
        this.i = i;
    }

    public int hashCode() {
        return i % ;
    }

    public final static void main(String[] args) {
        HashTest a = new HashTest();
        HashTest b = new HashTest();
        a.setI();
        b.setI();
        Set<HashTest> set = new HashSet<HashTest>();
        set.add(a);
        set.add(b);
        System.out.println(a.hashCode() == b.hashCode());
        System.out.println(a.equals(b));
        System.out.println(set);
    }
}
           

輸出結果

true
false
[com.ubs.sae.test.HashTest@1, com.ubs.sae.test.HashTest@1]
           

在這個例子中,我們将唯一辨別符進行一個%運算生成一個hashcode

看起來并不複雜,但是最基本就是要符合hashcode()方法的要求。

equel(Object o)沒有重寫,預設的是比較兩個對象記憶體位置是否相同,是以兩個對象在這裡是不同的。set集合儲存了這兩個對象。

接下來我們來重寫equel(Object o)方法 通過Id唯一辨別符進行判斷對象是否相同

public class HashTest {
    private int i;

    public int getI() {
        return i;
    }

    public void setI(int i) {
        this.i = i;
    }

    public boolean equals(Object object) {
        if (object == null) {
            return false;
        }
        if (object == this) {
            return true;
        }
        if (!(object instanceof HashTest)) {
            return false;
        }
        HashTest other = (HashTest) object;
        if (other.getI() == this.getI()) {
            return true;
        }
        return false;
    }

    public int hashCode() {
        return i % ;
    }

    public final static void main(String[] args) {
        HashTest a = new HashTest();
        HashTest b = new HashTest();
        a.setI();
        b.setI();
        Set<HashTest> set = new HashSet<HashTest>();
        set.add(a);
        set.add(b);
        System.out.println(a.hashCode() == b.hashCode());
        System.out.println(a.equals(b));
        System.out.println(set);
    }
}
           

輸出結果

true
true
[com.ubs.sae.test.HashTest@1]
           

可以看出當Id相同時,兩個對象被判定為相同且HashSet表中也隻能儲存一個。

當equel(Object o)認為兩個對象相同時,hashcode也相同

http://blog.csdn.net/fenglibing/article/details/8905007