Java雜談——你真的會重寫Equals方法嗎
什么是equals方法
Java中用equals方法來判斷兩個對象是不是相等,equals方法是Object類就擁有的方法,因此所有類都擁有該方法,使用方式很簡單:a.equals(b) ,返回true或false。
Object中的equals方法的源碼
- public boolean equals(Object obj) {
- return (this == obj);
- }
為什么需要重寫equals方法
從object處的繼承來了equals僅僅判斷了2個對象的內存地址是否一樣,這樣的代碼,沒辦法滿足大部分的情況,因此新建的類如果需要使用equals方法就需要重寫equals方法。
重寫equals方法需要遵守的規(guī)范
1、自反性:對于任何非空引用x,x.equals(x)應該返回true。
2、對稱性:對于任何引用x和y,如果x.equals(y)返回true,那么y.equals(x)也應該返回true。
3、傳遞性:對于任何引用x、y和z,如果x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)也應該返回true。
4、一致性:如果x和y引用的對象沒有發(fā)生變化,那么反復調用x.equals(y)應該返回同樣的結果。
5、非空性:對于任意非空引用x,x.equals(null)應該返回false。
equals和hashCode
每個覆蓋了equals方法的類中,必須覆蓋hashCode。如果不這么做,就違背了hashCode的通用約定。
equals和hashCode都是用來判斷兩個對象是否相等,區(qū)別是:
- equals - 保證比較對象是否是絕對相等的
- hashCode - 保證在最快的時間內判斷兩個對象是否相等,可能有誤差值
在hashMap里面的put方法中,先根據(jù)hashcode找到對應下標。如果該下標對應的列表已經存在數(shù)據(jù),則對列表進行逐個遍歷,遍歷的時候使用equals判斷是否是相同對象。如果找到相同對象則進行更新操作,找不到則進行插入操作。
假設現(xiàn)在存在2個equals為true,但是hashCode不一樣的key往同一個hashMap里面添加,因為hashCode不一樣,導致他們計算出來的下標大概率是不一樣的(不一樣的概率大于93%)。我們繼續(xù)假設他們的下標計算出來不一樣,那么當?shù)诙€key存入的時候,因為檢測的是另外一個列表,就無法發(fā)現(xiàn)第一個key的存在,因此會執(zhí)行插入操作。
這樣引發(fā)的問題就是在同一個hashMap中,同一個key(equals一樣),但是存在兩條數(shù)據(jù)。