閱讀原文:不同時重寫equals和hashCode又怎樣!
可能一問到equals和hashCode相關的問題,就會有人講他們的自反性,對稱性,一致性,傳遞性等幾條約定了,
此時我不得不佩服,這么多約定竟然都能記得,但我不知道你是不是真的理解呢。
我只能說只要你不碰到這幾個主,你也沒什么事的!
為什么不能遇到它們幾個呢?
因為它們幾個會用到hashCode方法。
他們用hashCode方法來干嘛?
hashCode方法是根據對象的地址生成的一個int整數,默認它和地址一一對應的,如果不重寫,那么只有對象地址一樣的情況下,哈希值才相等。
equals默認用來比較地址是否相同,但當集合中元素增多時,再使用equals判斷,效率是比較低的;而哈希值是可以快速定位到指定的元素的,
所以默認Java就使用哈希值來比較定位,因此有了Object.hashCode的約定。
Set怎么實現存儲不重復的元素的?HashMap怎么判斷相同的key的?有興趣可去深入了解一下。
例子小王在「堆」中有兩套房產,這兩套房產位于不同的地址。現在我想要判斷這兩套房子是否是同一個主人?
于是我去問Object,而Object告訴我這兩套房產不是一個人的!
我:為什么呢?
Object: equals告訴我兩套房子離了十萬八千里,在不同的地方(地址),當然不是同一個人了。
我:這邏輯……(不符合我們常規的認知啊)
既然這樣,那我只能重寫equals了!
//注意:這是偽代碼,省略了很多 //重寫equals,認為身份證相同就是同一個人 @Override public boolean equals(Object obj) { return this.idCard == obj.idCard; }
哈哈,好啦,現在equals終于知道這兩個房子是同一人的啦!
然而在房產管理局(HashMap)我得到一個消息:小王只要一套房產!
WTF!我白干了!
房產管理局(HashMap): 不信你看!
HashMap
遇到你真是倒霉了,原來房產管理局(HashMap)使用了hashCode來計算的!想要正確的統計小王的房產只能重寫hashCode方法了。
@Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (idCard != null ? idCard.hashCode() : 0); return result; }
此時,他們統計終于對了!!!
總結除非你能保證你重寫equals的類不被Set,Map使用,否則你就必須同時重寫equals和hashCode。
你能保證嗎?如果不想同時重寫,你可以這樣:
/** * 1.此類應用于Set,Map時,需要使用者重寫hashCode,違規者后果自負 * 2.本類不能作為第三方類庫供其他項目使用 * @author flyhero * @date 2019-04-03 6:14 PM */ public class User {}
信不信這樣寫,老大看到后,就say goodbye了!
如何重寫equals與hashCode我就不寫出常說的那些約定性質了,寫了也記不住。說說如何避免違反這些約定:
重寫equals通過==判斷是否是同一個引用
通過instanceof判斷是否是相同類型
把參數轉為正確的類型
對比雙方各個屬性值是否相同
如:
@Override public boolean equals(Object obj) { if (this == obj) { return true; } if (!(obj instanceof User)) { return false; } User user = (User) obj; return this.name.equals(user.name) && this.idCard.equals(user.idCard); }重寫hashCode
hashCode方法應該為“不相等的對象產生不相等的哈希值”
一般計算是根據你equals中用來比較的屬性的hashCode組合計算的,不過目前JDK和一些類庫已經給我提供了很好的重寫方式,我們可不必去深究其中算法。
方式一
@Override public int hashCode() { return Objects.hash(name, idCard); }
使用了JDK自帶Objects提供的靜態方法。
方式二
@EqualsAndHashCode public class User {}
使用了lombok類庫,直接在類上注解即可。
更多精彩技術文章盡在微信公眾號:碼上實戰
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/77480.html
摘要:它也是用來判斷兩個對象是否相等,所以也得分不同的情況來說明。什么是的作用是獲取哈希碼,也稱為散列碼它返回的一個整數。這個哈希碼的作用是確定該對象在哈希表中的索引位置。它定義在的中,這就意味著中的任何類都包含有函數。 前言 萬丈高樓平地起,今天的聊點基礎而又經常讓人忽視的話題,比如==與equals()區別?為何當我們重寫完equals()后也要有必要去重寫hashcode()呢? .....
摘要:如果我們不重寫的方法,那么就會默認調用的方法小王小王我們可以看到以上的運行結果違背了的規定如果返回,那么方法必須返回相同的整數所以我們需要對對象的方法進行重寫通過重寫讓其與對象的屬性關聯起來,那么就能夠達到為,那么的值也相等。 面試官讓你說說==和equals()的區別,重寫equals必須重寫hashcode方法嗎 本身特質來說 ==:操作符 equals():方法 適用...
摘要:中,任何未處理的受檢查異常強制在子句中聲明。運行時多態是面向對象最精髓的東西,要實現運行時多態需要方法重寫子類繼承父類并重寫父類中已 1、簡述Java程序編譯和運行的過程:答:① Java編譯程序將Java源程序翻譯為JVM可執行代碼--字節碼,創建完源文件之后,程序會先被編譯成 .class 文件。② 在編譯好的java程序得到.class文件后,使用命令java 運行這個 .c...
摘要:中,任何未處理的受檢查異常強制在子句中聲明。運行時多態是面向對象最精髓的東西,要實現運行時多態需要方法重寫子類繼承父類并重寫父類中已 1、簡述Java程序編譯和運行的過程:答:① Java編譯程序將Java源程序翻譯為JVM可執行代碼--字節碼,創建完源文件之后,程序會先被編譯成 .class 文件。② 在編譯好的java程序得到.class文件后,使用命令java 運行這個 .c...
摘要:這樣做的目的是提高取對象的效率。在單線程情況下效率較高在的多線程情況下,同步操作能保證程序執行的正確性。 突然發現整理了很多筆記,應該放這里做備用 Hashtable和HashMap 主要區別:線程安全性,同步(synchronization),以及速度。 HashMap幾乎可以等價于Hashtable,除了HashMap是非synchronized的,并可以接受null。Hashta...
閱讀 3414·2021-11-24 09:38
閱讀 3193·2021-11-22 09:34
閱讀 2106·2021-09-22 16:03
閱讀 2364·2019-08-29 18:37
閱讀 377·2019-08-29 16:15
閱讀 1767·2019-08-26 13:56
閱讀 862·2019-08-26 12:21
閱讀 2204·2019-08-26 12:15