為什么重寫equals一定要重寫hashCode方法?


大家都知道,equals和hashcode是java.lang.Object類的兩個重要的方法,在實際應用中常常需要重寫這兩個方法,但至於為什么重寫這兩個方法很多人都搞不明白。

下面我們看下Object類中默認的equals和hashCode方法的實現:

1     public boolean equals(Object obj) { 2         return (this == obj); 3  } 4 
5     public native int hashCode();

 

  

以上是Object類關於這兩個方法的源碼,Object類默認的equals比較規則就是比較兩個對象的內存地址。而hashcode是本地方法,但實際上,hashcode是根據對象的內存地址經哈希算法得來的。

 1 import lombok.AllArgsConstructor;  2 import lombok.Data;  3 
 4 /**
 5  * Created by ganbo on 2019/6/17.  6  */
 7 
 8 @Data  9 @AllArgsConstructor 10 public class User { 11     private Long id; 12     private String name; 13 
14  @Override 15     public boolean equals(final Object o) { 16         if (this == o) return true; 17         if (!(o instanceof User)) return false; 18         if (super.equals(o)) return true; 19 
20         final User user = (User) o; 21 
22         if (id != null ? !id.equals(user.id) : user.id != null) return false; 23         return name != null ? name.equals(user.name) : user.name == null; 24  } 25 
26  @Override 27     public int hashCode() { 28         int result = 1; 29         result = 31 * result + (id != null ? id.hashCode() : 0); 30         result = 31 * result + (name != null ? name.hashCode() : 0); 31         return result; 32  } 33 
}

上面代碼展示了重寫equals和hashCode方法后的User類,線有如下代碼:

1     public static void main(String[] args) { 2         User u1 = new User(1L, "root"); 3         User u2 = new User(1L, "root"); 4 
5  System.out.println(u1.equals(u2)); 6         System.out.println(u1.hashCode() == u2.hashCode()); 7     }

此時u1.equals(u2)一定返回true,假如只重寫equals而不重寫hashCode,那么User類的hashCode方法默認就是繼承父類Object的hashCode方法,由於默認的hashCode方法是根據對象的內存地址

經過hash算法得來的,顯然此時u1對象和u2對象的hashCode值不一定相等,這個時候將該對象作為HashMap的key就會出現問題,跟期望的不一致(兩個對象equals,卻存在MashMap的兩個槽上)。

然而重寫了equals,且u1.equals(u2)返回true,根據hashcode的規則,兩個對象相等其哈希值一定相等,所以矛盾就產生了,因此重寫equals一定要重寫hashcode,而且從類重寫后的hashcode方法中可以看出,

重寫后返回的新的哈希值與User的兩個屬性有關。

以下是關於hashcode的一些規定:

兩個對象相等,hashcode一定相等

兩個對象不等,hashcode不一定不等

hashcode相等,兩個對象不一定相等

hashcode不等,兩個對象一定不等

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM