在 Java 中,hashcode
?和?equals
?方法是?Object
?類的兩個重要方法,它們在處理對象比較和哈希集合(如?HashMap
、HashSet
)時起著關鍵作用。對于equals大部分Java程序員都不陌生,它通常是比較兩個對象的內容(值)是否相等(==雙等于比較對象的內存地址),如果是Object中的equals方法默認就是比較內存地址(在沒有被重寫的情況下和==一樣)。
hashCode
?方法返回對象的哈希值。哈希碼是一個整數值,主要用于在哈希表(如?HashMap
、HashSet
)中快速定位對象。hashcode的值默認由JVM使用隨機數生成的。
使用哈希碼值的目的是為了判斷元素是否存在哈希表中,如果使用equals來查詢效率會很低。如果哈希表中沒有這個對象對應的hashcode值,那么就可以確定這個對象在哈希表中不存在,存入到哈希表中;如果存在相同的hashcode值,就調用equals方法與新的元素進行比較,相同就直接覆蓋,不相同就散列到其他的地址。
- 默認實現:
Object
?類中的?hashCode
?方法基于對象的內存地址生成哈希碼。 - 重寫原則:當重寫?
equals
?方法時,通常也需要重寫?hashCode
?方法。這是因為在哈希集合中,首先會根據對象的哈希碼值來確定對象所在的桶(bucket),然后再使用?equals
?方法來確定桶內的具體位置。如果兩個對象通過?equals
?方法比較相等,但它們的?hashCode
?方法返回不同的值,那么在哈希集合中這兩個對象可能會被存儲在不同的位置,導致哈希集合無法正確工作。
重寫?hashCode
?方法的一般原則是:
- 如果兩個對象通過?
equals
?方法比較相等,那么它們的?hashCode
?方法必須返回相同的值。 - 如果兩個對象通過?
equals
?方法比較不相等,它們的?hashCode
?方法返回的值不一定不同,但盡量使不同對象的哈希碼值分散,以提高哈希表的性能。
簡而言之,兩個對象equals相等,那么hashcode一定相等;兩個對象equals不相等,hashcode可有可能相等,這個就稱為哈希沖突。解決哈希沖突通常使用線性探測或者二次探測,這里就不具體展開了。
public class Person {private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic int hashCode() {return Objects.hash(name, age);}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Person person = (Person) o;return age == person.age &&Objects.equals(name, person.name);}
}
在上述?Person
?類的例子中,hashCode
?方法使用?Objects.hash
?方法根據?name
?和?age
?字段生成哈希碼,確保了相等的?Person
?對象具有相同的哈希碼。這樣在使用哈希集合存儲?Person
?對象時,能保證數據的一致性和高效訪問。
需要注意的是,當我們重寫equals() 方法,就一定要重寫hashCode()方法,因為如果我們只重寫equals方法,就有可能導致hashcode不相同,這樣就會導致這個類無法和所有的集合類一起工作。