閱讀原文:不一樣時重寫equals和hashCode又怎樣!java
可能一問到equals和hashCode相關的問題,就會有人講他們的自反性,對稱性,一致性,傳遞性等幾條約定了, 此時我不得不佩服,這麼多約定居然都能記得,但我不知道你是否是真的理解呢。算法
我只能說只要你不碰到這幾個主,你也沒什麼事的!微信
爲何不能遇到它們幾個呢?ide
由於它們幾個會用到hashCode方法。this
他們用hashCode方法來幹嗎?spa
hashCode方法是根據對象的地址生成的一個int整數,默認它和地址一一對應的,若是不重寫,那麼只有對象地址同樣的狀況下,哈希值才相等。code
equals默認用來比較地址是否相同,但當集合中元素增多時,再使用equals判斷,效率是比較低的;而哈希值是能夠快速定位到指定的元素的, 因此默認Java就使用哈希值來比較定位,所以有了Object.hashCode的約定。orm
Set怎麼實現存儲不重複的元素的?HashMap怎麼判斷相同的key的?有興趣可去深刻了解一下。cdn
小王在「堆」中有兩套房產,這兩套房產位於不一樣的地址。如今我想要判斷這兩套房子是不是同一個主人?對象
因而我去問Object,而Object告訴我這兩套房產不是一我的的!
我:爲何呢?
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類庫,直接在類上註解便可。
更多精彩技術文章盡在微信公衆號:碼上實戰