1、原因
Object 的 equals() 默認比較的是對象的內存地址,而 hashCode() 也是對對象的內存地址進行hash。
因為Hash比equals方法的開銷要小,速度更快,所以在涉及到hashcode的容器中(比如HashSet),判斷自己是否持有該對象時,會先檢查hashCode是否相等,如果hashCode不相等,就會直接認為不相等,並存入容器中,不會再調用equals進行比較。
這樣就會導致,即使該對象已經存在HashSet中,但是因為hashCode不同,還會再次被存入。因此要重寫hashCode保證:如果equals判斷是相等的,那hashCode值也要相等。
2、測試
場景:創建一個Product對象,認為商品id相等就是同一個對象。
(1)只重寫equals方法,不重寫hashcode方法
package com.yang.servlet; import java.util.HashSet; import java.util.Objects; public class Product { private Integer id; private String name; public Product(Integer id, String name) { this.id = id; this.name = name; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } // 重寫equals @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Product product = (Product) o; return Objects.equals(id, product.id); } public static void main(String[] args) { Product product1 = new Product(1, "包子"); Product product2 = new Product(1, "饅頭"); HashSet<Product> products = new HashSet<Product>(); products.add(product1); products.add(product2); // 使用equals判斷是否相等 System.out.println(product1.equals(product2)); // 查看HashSet中元素個數 System.out.println(products.size()); } }
測試結果:
true // 可以看到判斷是相等的 2 // 但是還是存到了HashSet中
雖然id相同,但是還是添加到了hashSet中。
(2)重寫hashcode方法
@Override public int hashCode() { return Objects.hash(id); }
測試結果:
true // 可以看到判斷是相等的 1 // 並且第二個值並沒有存到HashSet中