愛問面試題:==和equals()和Hashcode()三者的理解

重寫前java

* ==表示兩個對象的內存地址

* equals()也表示對象內存地址

*  hashCode()表示該對象在JVM中的32位內存地址
重寫後:
==仍表示兩個對象的內存地址
 equals()表示連個對象的值是否相等,相等就視爲同一個對象
 若是equals()方法重寫,那麼hashCode()方法也要重寫,由於要保證同一個對象的hashCode值相等這樣的規定。

根據javaAPI文檔上的介紹:程序員

(1)、同一個對象的hashCode值必定相同,不管是否重寫過equals()方法,也就是說重寫過之後他們的值相等了,那麼他們的hashCode也要保持相等,因此就也要重寫hashCode()方法。算法

(2)、若是兩個對象不相等,那麼對這兩個對象中的任一對象上調用 hashCode 方法不 要求必定生成不一樣的整數結果。可是,程序員應該意識到,爲不相等的對象生成不一樣整數結果能夠提升哈希表的性能。ide

好比重寫後的hashCode方法以下:性能

@Override測試

    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        result = prime * result + sex;
        return result;
    }

比較兩個對象是否相等:this

(1)先比較連個對象的hashCode值是否相等,若是相等則比較(2)(由於不一樣的對象也有可能hashCode值相等),若是不等則必定不是同一個對象code

(2)再比較equals()方法,若是相等則視爲贊成對象,反之則不是同一個對象。**對象

二、hashCode()和equals()關係是什麼?
明白幾個原則:
equals相等的兩個對象,hashcode必定相等。
equals不相等的兩個對象,hashcode不必定不相等。
hashcode不相等,那麼equals是必定不等的。
hashcode相等,equals可能相等,也可能不等

解釋下第四個原則:
就比如hashcode像是一個詞典目錄裏的按字母爲索引查找字,查一個「Z」拼音開頭的詞,下面等查到「本身」,「自我」,「知道」等詞,用equals就是判斷這些詞語當中是否有相等的詞,「本身」和「知道」兩個詞不相等的,因此equals值不等,但它們同屬於"Z"開頭的詞因此它們hashcode值相等。索引

三、爲何重寫equals的同時也要重寫hashCode呢?
hash算法是爲了提升equals比較的效率而被髮明出來的。這點在集合方面就能體現出來,就好比在List或Set集合裏要比較是否有重複元素,當發現某個集合對象與另外一個集合對象equals比較的結果相等時,則中止查找返回true值,反之,返回false值。
但若是集合中有大量元素呢,假設一個集合A裏有10萬元素,並且另外一個比較的對象B中還可能沒有重複的值,則意味着其實不用比較我都知道二者不相同,但程序依然會對集合A裏遍歷10萬元素而後和B進行逐一排查。。。又或者當我要加入第100001個數據我要驗證前面元素有重複值,就要跟前面10萬個元素一一比較,效率可想而知很低。

哈希算法就是Java系統首先調用對象的hashCode()方法得到該對象的哈希碼錶,而後根據哈希碼找到相應的存儲區域,若哈希碼相同在取得該存儲區域內的每一個元素與該對象進行equals方法比較,若不一樣也就沒有繼續比較的必要了,這對於數量較大的狀況效率就提升了很多,重寫hashcode方法,最主要就是保證操做的元素在同一個對象裏且值都沒有重複,若沒有重寫hashcode,可能會出現將對象引用不一樣,但元素徹底相同的集合進行操做。

下面寫一個例子

package demo;

public class override_HshCode_Equals {
public int x;
public int y;

public override_HshCode_Equals(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;
}

/**
 * equals返回false就說明沒有重複項能夠添加
 * true是重複不能添加
 */
@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;

    final override_HshCode_Equals heClass = (override_HshCode_Equals) obj;
    //這裏就對實例化對象裏的x,y進行比較
    if (x != heClass.x) {
        return false;
    }
    if (y != heClass.y) {
        return false;
    }
    return true;
}

}

測試類

package demo;

import java.util.HashSet;

public class TestMain {
    public static void main(String[] args) {
        HashSet<override_HshCode_Equals> set = new HashSet<override_HshCode_Equals>();
        override_HshCode_Equals heClass1 = new override_HshCode_Equals(1, 1);
        override_HshCode_Equals heClass2 = new override_HshCode_Equals(5, 5);
        override_HshCode_Equals heClass3 = new override_HshCode_Equals(1, 1);
        set.add(heClass1);
        set.add(heClass2);
        set.add(heClass3);
        set.add(heClass1);
        System.out.println("set數量=" + set.size());
    }
}
結果以下

set數量=2

注:重寫override_HshCode_Equals類的hashCode至關於自定義返回了一個「哈希碼」,對比x,y值是否相等,先比較hashcode值,heClass1(3,3)==heClass3(3,3),因此它們的hashcode值相等,可是heClass2的x,y和heClass1,heClass3的x,y值不等,因此hashcode不等,equals必定不等,因此heClass2對象是能夠add進去的。前面說了heClass1和heClass3的hashcode值相等,而後進入equals進行對比,發現二者的對象都是相同的,根據程序add循序來看,因此heClass1是能夠add進去的,而後heClass3和後面add(heClass1)都爲重複項,就不會添加

相關文章
相關標籤/搜索