java:equals與hascode( )

Java中的equals方法和hashcode方法是Object中的,所以每個對象都是有這兩個方法的,有時候我們需要實現特定需求,可能要重寫這兩個方法。

1.區別

eqauls()和hashcode()方法是用來在同一類中做比較用的,尤其是在容器裏如set存放同一類對象時用來判斷放入的對象是否重複。這裏我們首先要明白一個問題:

1,equals()相等的兩個對象,hashcode()一定相等,equals()不相等的對象,卻並不能證明他們的hashcode()不相等。換句話說,equals()方法不相等的兩個對象,hashcode() 有可能相等。(我的理解是由於哈希碼在生成的時候產生衝突造成的)
2,在這裏hashcode() 就好比字典裏每個字的索引,equals()好好比比較的是字典裏同一個字下的不同詞語。就好像在字典裏面查“自”這個字下的兩個詞語“自己”和“自發”。
3,反過來,hashcode不等,一定能推出equals()也不等;hashcode()相等,equals()可能相等,也可能不相等。
4,在object類中,hashcode()方法是本地方法,返回的是對象的地址值,而object類中的equals()方法比較的也是兩個對象的地址值,如果equals()相等,說明兩個對象地址值也相等,當然hashcode() 也就相等了。

2.hashcode()的用法

1,有人發明了一種哈希算法來提高從集合中查找元素的效率,這種方式將集合分成若干個存儲區域,每個對象可以計算出一個哈希碼,可以將哈希碼分組(使用不同的hash函數來計算的),每組分別對應某個存儲區域,根據一個對象的哈希嗎就可以確定該對象應該存儲在哪個區域HashSet就是採用哈希算法存取對象的集合,它內部採用對某個數字n進行取餘(這種的hash函數是最簡單的)的方式對哈希碼進行分組和劃分對象的存儲區域;
2,Object類中定義了一個hashCode()方法來返回每個Java對象的哈希碼,當從HashSet集合中查找某個對象時,Java系統首先調用對象的hashCode()方法獲得該對象的哈希碼錶,然後根據哈希嗎找到相應的存儲區域,最後取得該存儲區域內的每個元素與該對象進行equals方法比較;這樣就不用遍歷集合中的所有元素就可以得到結論,可見,HashSet集合具有很好的對象檢索性能,
3,但是,HashSet集合存儲對象的效率相對要低些,因爲向HashSet集合中添加一個對象時,要先計算出對象的哈希碼和根據這個哈希碼確定對象在集合中的存放位置爲了保證一個類的實例對象能在HashSet正常存儲,要求這個類的兩個實例對象用equals()方法比較的結果相等時,他們的哈希碼也必須相等;也就是說,如果obj1.equals(obj2)的結果爲true,那麼以下表達式的結果也要爲true:
obj1.hashCode() == obj2.hashCode()

換句話說:當我們重寫一個對象的equals方法,就必須重寫他的hashCode方法,不過不重寫他的hashCode方法的話,Object對象中的hashCode方法始終返回的是一個對象的hash地址,而這個地址是永遠不相等的。所以這時候即使是重寫了equals方法,也不會有特定的效果的,因爲hashCode方法如果都不想等的話,就不會調用equals方法進行比較了,所以沒有意義了。

3.例子

package com.weijia.demo;

public class RectObject {
    public int x;
    public int y;
    public RectObject(int x,int y){
        this.x = x;
        this.y = y;
    }
    @Override
    public int hashCode(){
        final int prime = 31;
        int result = 1;
        result = prime * result + x;
        result = prime * result + y;
        return result;
    }
    @Override
    public boolean equals(Object obj){
        if(this == obj)
            return true;
        if(obj == null)
            return false;
        if(getClass() != obj.getClass())
            return false;
        final RectObject other = (RectObject)obj;
        if(x != other.x){
            return false;
        }
        if(y != other.y){
            return false;
        }
        return true;
    }
}

4.重要的點

如果我們將對象的屬性值參與了hashCode的運算中,在進行刪除的時候,就不能對其屬性值進行修改,否則會出現嚴重的問題。

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