一言以蔽之:重寫 equals 方法是為了比較物件的內容是否相等,重寫 hashCode 方法是為了保證物件在哈希表等資料結構中的正確性,
1、在 Java 中,如果一個類重寫了 equals 方法,則必須同時重寫 hashCode 方法,這是因為在 Java 中,物件的 hashCode 值用于在哈希表(Hash Table)等資料結構中進行快速查找,而哈希表的實作原理是根據物件的 hashCode 值進行散列(Hash),所以如果兩個物件的 equals 方法回傳 true,則它們的 hashCode 值也必須相等,否則可能會導致哈希表的查詢等操作出現錯誤結果,
以下是一個示例,演示了為什么需要同時重寫 equals 和 hashCode 方法:
public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof Person)) return false; Person person = (Person) obj; if (age != person.age) return false; if (name != null ? !name.equals(person.name) : person.name != null) return false; return true; } }
如果只重寫了 equals 方法,而沒有重寫 hashCode 方法,則可能會導致哈希表中出現錯誤的結果:
Person p1 = new Person("Alice", 18); Person p2 = new Person("Alice", 18); Map<Person, String> map = new HashMap<>(); map.put(p1, "Hello"); // 此時嘗試獲取 p2 對應的值,由于沒有重寫 hashCode 方法,p1 和 p2 的 hashCode 值不相等 // 因此,雖然 p1 和 p2 的 equals 方法回傳 true,但是從哈希表中獲取 p2 對應的值時卻會失敗 String value = https://www.cnblogs.com/dk1024/archive/2023/04/02/map.get(p2); // value 為 null
2、下面是一個重寫了 hashCode 方法的示例代碼:
public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!(obj instanceof Person)) return false; Person person = (Person) obj; if (age != person.age) return false; if (name != null ? !name.equals(person.name) : person.name != null) return false; return true; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + age; return result; } }
在上面的示例代碼中,hashCode 方法重寫的實作邏輯與 equals 方法的實作邏輯是一致的,都是比較 Person 物件的兩個屬性 name 和 age 是否相等,如果相等則回傳相同的 hashCode 值,
需要注意的是,這里的 31 是一個質數,它的作用是為了避免哈希沖突,因為 31 的乘法運算比較快,而且相對來說能夠更加均勻地散布哈希值,從而減少哈希沖突的發生,
重寫了 hashCode 方法之后,就可以保證在哈希表等資料結構中,同一個物件的 hashCode 值不變,不同物件的 hashCode 值不同,從而能夠正確地進行查找和比較操作,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/548955.html
標籤:其他
下一篇:任何Bean通過實作ProxyableBeanAccessor介面即可獲得動態靈活的獲取代理物件或原生物件的能力
