Java中重寫equals方法為什麼要重寫hashcode方法?

2020-12-21 計算機java編程

== 與 equals的區別

如果兩個引用類型變量使用==運算符,那麼比較的是地址,它們分別指向的是否是同一地址的對象。結果一定是false,因為兩個對象不可能存放在同一地址處。要求是兩個對象都不是能空值,與空值比較返回false。==不能實現比較對象的值是否相同。所有對象都有equals方法,默認是Object類的equals,其結果與==一樣。如果希望比較對象的值相同,必須重寫equals方法。hashCode與equals的區別

Object中的equals:

equals 方法要求滿足:

自反性 a.equals(a)對稱性 x.equals(y) y.equals(x)一致性 x.equals(y) 多次調用結果一致對於任意非空引用x,x.equals(null) 應該返回falseObject中的hashCode:

它是一個本地方法,它的實現與本地機器有關,這裡我們暫且認為他返回的是對象存儲的物理位置。

當equals方法被重寫時,通常有必要重寫hashCode方法,以維護hashCode方法的常規約定:值相同的對象必須有相同的hashCode。object1.equals(object2)為true,hashCode也相同;hashCode不同時,object1.equals(object2)為false;hashCode相同時,object1.equals(object2)不一定為true;當我們向一個Hash結構的集合中添加某個元素,集合會首先調用hashCode方法,這樣就可以直接定位它所存儲的位置,若該處沒有其他元素,則直接保存。若該處已經有元素存在,就調用equals方法來匹配這兩個元素是否相同,相同則不存,不同則鏈到後面(如果是鏈地址法)。

先調用hashCode,唯一則存儲,不唯一則再調用equals,結果相同則不再存儲,結果不同則散列到其他位置。因為hashCode效率更高(僅為一個int值),比較起來更快。

HashMap#put源碼

hash是key的hash值,當該hash對應的位置已有元素時會執行以下代碼(hashCode相同)

如果equals返回結果相同,則值一定相同,不再存入。

如果重寫equals不重寫hashCode會怎樣

兩個值不同的對象的hashCode一定不一樣,那麼執行equals,結果為true,HashSet或HashMap的鍵會放入值相同的對象。

話不多說,直接上例子,~~~

首先我們只重寫equals()方法

看我們的測試類

依次輸出

是否出現矛盾???用equals比較說明對象相同,但是在HashMap中卻以不同的對象存儲(沒有重寫hascode值,兩個hascode值,在他看來就是兩個對象)。到底這兩個對象相等不相等????說明必須重寫hashCode()的重要性,

接下來重寫重寫equals方法和hashCode方法,再比較

測試類

依次輸出

看到這裡,同學 你懂了嗎?還不懂,可以自己實現一遍代碼。

相關焦點

  • Java為什麼重寫equals一定要重寫hashCode?
    初步探索首先我們要了解equals方法是什麼,hashcode方法是什麼。equals方法equals 是java的obejct類的一個方法,equals的源碼如下:由此我們可以看到equals是用來比較兩個對象的內存地址是否相等。
  • 重寫equals之後,師哥一行一行教你重寫hashcode方法
    引言師哥程式設計師交流群裡,上次那位剛剛入門的兄弟,在看完我為他寫的《你真的了解,JAVA中equals方法背後的細節嗎?》之後。立馬就來告訴我喜訊,他按著師哥的步驟,成功地寫出漂亮,正確,完美的equals方法。但俗話說,樂極生悲是有道理的,前話剛落三秒,就有了下面的對話。
  • java中雙等號和equals的區別,重寫equals時要重寫hashcode
    也分兩種情況:如果沒有對equals方法進行重寫,則比較的是引用類型的變量所指向的對象的地址,,這個和==號比較對象或者引用類型是一樣的效果例如String、Date等類對equals方法進行了重寫,比較的是所指向的對象的內容。
  • 「原創」不重寫equals和hashcode難道就不行嗎?
    本文轉載自【微信公眾號:java進階架構師,ID:java_jiagoushi】經微信公眾號授權轉載,如需轉載與原文作者聯繫究竟為什麼要重寫equals和hashcode???>2、Hash算法介紹3、重寫equals()方法和hashCode()方法3.1、什麼時候需要重寫?
  • java超類Object解析及Object常用方法
    看下 Object 類中有哪些方法:關於 native 修飾詞的說明:native 修飾的方法是一個原生態方法,方法對應的實現不是在當前文件,而是在用其他語言中(如 C、C++),所以效率上一般比 java 語言實現的方法要高。
  • 萬字梳理,帶你拿下 Java 面試題!
    equals 方法是 Object 類定義的方法,Object 是所有類的父類,當然也包括 String,String 重寫了 equals 方法,下面我們來看看是怎麼重寫的:首先會判斷要比較的兩個字符串它們的引用是否相等。
  • java之繼承中方法覆蓋重寫的簡單介紹
    各位小夥伴們大家好,這次,小編要介紹的是繼承當中方法的覆蓋重寫(Override),什麼是方法的覆蓋重寫呢?在繼承的關係中,方法的名稱一樣,參數列表也一樣。之前小編要有介紹過方法的重載(Overload),方法名稱不一樣,參數列表不一樣,具體大家可以參考這篇文章
  • 重載/重寫,我們的方法是如何被執行的
    正題為了避免不必要的浪費時間,文章主要是圍繞倆點進行展開:1、重載為什麼根據靜態類型,而非動態類型?2、我們重載/重寫了這麼多方法,是怎麼被準確的定位到的?但是為什麼重載的demo運行結果是這個呀?我覺得它應該一個是Im Language一個是Hi Java呀。畢竟我在調用方法時,參數一個傳的實例化的類型一個Java,一個是Languae,為啥不一個匹配參數是Java類型,一個匹配參數Language類型啊?
  • Java 重載、重寫、構造函數詳解
    ."); } }2、對於從父類繼承來的抽象方法,要麼在子類用重寫的方式設計該方法,要麼把子類也標識為抽象的。所以抽象方法可以說是必須要被重寫的方法。3、重寫的意義。重寫方法可以實現多態,用父類的引用來操縱子類對象,但是在實際運行中對象將運行其自己特有的方法。
  • 這個類在Java裡,是和亞當夏娃一樣的存在
    在西方神話體系中,人類是如何來的?是亞當夏娃的後代。今天要學的Object類在Java裡面,就好比是和亞當夏娃一樣的存在。只不過神話終歸只是神話,是虛無縹緲的,但是計算機裡面,Object類是真真實實存在的。
  • Java小知識:Object 組件的一些常見方法
    2、public boolean equals( Object obj)用於比較2個對象的內存地址是否相等,String類對該方法進行了重寫用戶比較字符串的值是否相等。這裡要特別注意,重寫的時候,如果該對象的成員含有成員對象的話,如果僅僅是調用 super.clone 的話,拷貝的對象中,裡面的成員對象並沒有被拷貝到,還是共用同一個成員對象,所以我們一般需要進行深度克隆。
  • java重載和重寫,你能正確區分嗎?
    我們在平時開發的時候經常會遇見這樣一個問題,方法的重載和重寫。有時候經常搞混,這篇文章就是為了很好的去整理區分一下。一個類中,可以有很多的構造方法,而且名字相同都是類名,其實這些方法就已經構成了重載。也就是說,在一個類中,可以有很多名字相同的不同方法。現在一個問題來了,就是java是如何區分這些方法的呢?方法重載其實區分重載,有一個很簡便的方法,那就是每一個方法有一個獨一無二的參數列表。
  • 在.NET中,C#基類編寫虛方法,而在子類中編寫重寫方法重寫邏輯
    方法重寫在編寫C#程序時,有時候需要在子類中編寫與基類同名的方法,但並不需要基類方法中的邏輯代碼,此時就需要重寫基類的方法來實現。C#方法重寫是指在子類中將基類中的同名方法代碼覆蓋掉,使用新的邏輯代碼替代。
  • Java基礎面試題簡單總結
    中的保留字,現在沒有在java中使用11、數組有沒有length()這個方法?如果在子類中定義某方法與其父類有相同的名稱和參數,我們說該方法被重寫 (Overriding)。子類的對象使用這個方法時,將調用子類中的定義,對它而言,父類中的定義如同被"屏蔽"了。如果在一個類中定義了多個同名的方法,它們或有不同的參數個數或有不同的參數類型,則稱為方法的重載(Overloading)。
  • Java 筆記
    在Object這個超類中繼承過來的有一些方法是可以被重寫的,比如toString(),equals(),hashCode(),finalize(),也有一些不能被重寫的方法,如wait(),notify(),notifyAll(),getClass()方法這些是final修飾的是不能被重寫的。
  • Java之File類的構造方法
    各位小夥伴們大家好,在之前的文章中,小編介紹了Java之File類的簡單介紹,File類的靜態成員變量,這次小編要介紹的是File類的構造方法。File("c:\\Users\\java\\code\\a.text");System.out.println(f1);//重寫了Object類的toString方法,列印的是一個路徑:c:\Users\java\code\a.textFile f2=new File("c:\\Users\\java\\code");System.out.println
  • 程式設計師:java中把一個list轉tree有哪幾種方法,推薦三種方法 - 程序...
    說到java把list轉tree,網上有一大堆文章,但是我看過之後發現基本都只說了遞歸和兩層嵌套循環兩種方法,沒人提到兩次遍歷的方法,我今天就把三種方法都實現以下,做一下對比問題周二面試中,面試官提了一個問題,當時答得不是特別好,手寫代碼能力還是不行啊,一個是比較緊張,一個是代碼沒法調試
  • 從字節碼看方法重載與重寫
    在Java中存在重載與重寫,面試中經常會出現與之相關的問題,今天從字節碼來看看他們的實現。簡單代碼簡單的測試代碼如下圖:其中有繼承關係的三個類Animal、Mamml(哺乳動物)、Tiger,主要用來實現重寫,AssignTest中有三個test方法用來實現重載,大家可以猜猜列印結果!