五分鐘搞懂hashCode()和equals()方法的原理

Java中的超類java.lang.Object 有兩個非常重要的方法:

public boolean equals(Object obj)
public int hashCode()

這兩個方法最開發(fā)者來說是十分重要的,必須清楚的理解,但實際上,甚至很多經(jīng)驗豐富的Java開發(fā)者有時候也沒有真正搞清楚這兩個方法的使用和原理。當(dāng)我們自定義了對象,并且想要將自定義的對象加到Map中時,我們就必須對自定義的對象重寫這兩個方法,才能正確使用Map。我們接下來將用這篇文章指出在使用hashcode和equals方法時,經(jīng)常范的錯誤,并指出如何正確的使用這兩個方法,以及這兩個方法工作的原理。

常見的誤區(qū)

看下面這段代碼:

import java.util.HashMap;

public class HashCodeEqual {
    public static void main(String[] args) {
        Apple a1 = new Apple("Blue");
        Apple a2 = new Apple("Green");
        
        HashMap<Apple, Integer> map = new HashMap<>();
        map.put(a1, 10);
        map.put(a2, 20);
        
        System.out.println(map.get(new Apple("Green")));
    }
}

class Apple {
    public String color;
    
    public Apple(String color) {
        this.color = color;
    }
    
    @Override
    public boolean equals(Object obj) {
        if(! (obj instanceof Apple))
            return false;
        if(obj == this)
            return true;
        return this.color.equals(((Apple)obj).color);
    }
}

我們執(zhí)行上面這段代碼

Paste_Image.png

卻發(fā)現(xiàn)與我們預(yù)想的結(jié)果并不一樣,我們想取出map中顏色為Green的apple,最后卻得到一個null值,這說明map沒有我們需要的顏色為green的apple對象,但實際上,我們明明向其中添加了一個顏色為green的apple對象,也重寫了equals方法,為什么最后卻取不出這個對象呢?

![Upload Paste_Image.png failed. Please try again.]

錯誤出現(xiàn)的原因

這個問題引起的原因是因為我們沒有重寫“hashCode”方法,這就需要我們深入理解equals方法和hashCode方法的原理:

  • 如果兩個對象是相等的,那么他們必須擁有一樣的hashcode,這是第一個前提
  • 如果兩個對象有一樣的hashcode,但仍不一定相等,因為還需要第二個要求,也就是equals方法的判斷。
    其實,map判斷對象的方法就是先判斷hashcode是否相等,如果相等再判斷equals方法是否返回true,只有同時滿足兩個條件,最后才會被認(rèn)為是相等的。
    Map查找元素比線性搜索更快,這是因為map利用hashkey去定位元素,這個定位查找的過程分成兩步,內(nèi)部原理中,map將對象存儲在類似數(shù)組的數(shù)組的區(qū)域,所以要經(jīng)過兩個查找,先找到hashcode相等的,然后在再在其中按線性搜索使用equals方法,通過這兩部來查找一個對象。
Paste_Image.png

就像上圖這個結(jié)構(gòu),每個hashcode對應(yīng)一個桶,每個tongli桶里還有多個對象,確定桶的方法是hashCode,在桶中遍歷線性查找的方法是equals。

在Object中的默認(rèn)的hashCode方法的實現(xiàn)是為不同的對象返回不同的hashcode,因此如果我們不重寫hashcode方法,那么沒有任何兩個對象會是相等的,因為object類中的hashcode實現(xiàn)是為不同的對象返回不同的hashcode。

所以,我們就搞清楚了上一段代碼出錯的原因,由于沒有重寫hashcode方法,所有的對象都是不一樣的,所以我們需要重寫hashcode方法,讓顏色的對象的hashcode是一樣的,比較直接的寫法就是直接用color的length作為hashcode。

public int hashCode(){
return this.color.length();
}
Paste_Image.png

** 切記,一定要同時重寫hashCode和equals方法 **

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,740評論 18 399
  • 一、前言 前段時間使用list.remove(obj)的時候重寫了obj的equals方法,因為list的remo...
    叫我宮城大人閱讀 5,852評論 5 16
  • 本文出自 Eddy Wiki ,轉(zhuǎn)載請注明出處:http://eddy.wiki/interview-java.h...
    eddy_wiki閱讀 1,224評論 0 16
  • 關(guān)于 “ == ” “ == ”操作符主要比較的是操作符兩端對象的內(nèi)存地址。如果兩個對象的內(nèi)存地址是一致的,那么就...
    EakonZhao閱讀 1,516評論 3 15
  • 夏日南風(fēng)不盡涼, 空明無影自飛揚(yáng)。 如約子夜生江面, 不速清晨入寢房。 頻掃牙床拂玉體, 屢吹殘醉戲紅妝...
    東林梁閱讀 1,153評論 7 38

友情鏈接更多精彩內(nèi)容