閱讀原文:不一樣時重寫equals和hashCode又怎樣!java
可能一問到equals和hashCode相關的問題,就會有人講他們的自反性,對稱性,一致性,傳遞性等幾條約定了,
此時我不得不佩服,這麼多約定居然都能記得,但我不知道你是否是真的理解呢。算法
我只能說只要你不碰到這幾個主,你也沒什麼事的!微信
由於它們幾個會用到hashCode方法。ide
hashCode方法是根據對象的地址生成的一個int整數,默認它和地址一一對應的,若是不重寫,那麼只有對象地址同樣的狀況下,哈希值才相等。this
equals默認用來比較地址是否相同,但當集合中元素增多時,再使用equals判斷,效率是比較低的;而哈希值是能夠快速定位到指定的元素的,
因此默認Java就使用哈希值來比較定位,所以有了Object.hashCode的約定。spa
Set怎麼實現存儲不重複的元素的?HashMap怎麼判斷相同的key的?有興趣可去深刻了解一下。code
小王在「堆」中有兩套房產,這兩套房產位於不一樣的地址。如今我想要判斷這兩套房子是不是同一個主人?對象
因而我去問Object,而Object告訴我這兩套房產不是一我的的!token
我:爲何呢?rem
Object: equals告訴我兩套房子離了十萬八千里,在不一樣的地方(地址),固然不是同一我的了。
我:這邏輯……(不符合咱們常規的認知啊)
既然這樣,那我只能重寫equals了!
//注意:這是僞代碼,省略了不少 //重寫equals,認爲身份證相同就是同一我的 @Override public boolean equals(Object obj) { return this.idCard == obj.idCard; }
哈哈,好啦,如今equals終於知道這兩個房子是同一人的啦!
然而在房產管理局(HashMap)我獲得一個消息:小王只要一套房產!
WTF!我白乾了!
房產管理局(HashMap): 不信你看!
HashMap<Object, Integer> roomManager = new HashMap<>(); public void count(){ User u1 = new User("小王", "34128"); countRoom(u1); User u2 = new User("小王", "34128"); countRoom(u2); } public void countRoom(User user){ boolean exist = roomManager.containsKey(user); if (exist) { Integer num = roomManager.get(user); roomManager.put(user, num++); }else { roomManager.put(user, 1); } }
遇到你真是倒黴了,原來房產管理局(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了!
我就不寫出常說的那些約定性質了,寫了也記不住。說說如何避免違反這些約定:
如:
@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方法應該爲「不相等的對象產生不相等的哈希值」
通常計算是根據你equals中用來比較的屬性的hashCode組合計算的,不過目前JDK和一些類庫已經給我提供了很好的重寫方式,咱們可沒必要去深究其中算法。
方式一
@Override public int hashCode() { return Objects.hash(name, idCard); }
使用了JDK自帶Objects提供的靜態方法。
方式二
@EqualsAndHashCode public class User {}
使用了lombok類庫,直接在類上註解便可。
更多精彩技術文章盡在微信公衆號:碼上實戰