爲什麼一個對象重寫了equals必須也重寫hashCode

一言以蔽之:重寫 equals 方法是爲了比較對象的內容是否相等,重寫 hashCode 方法是爲了保證對象在哈希表等數據結構中的正確性。


 

1、在 Java 中,如果一個類重寫了 equals 方法,則必須同時重寫 hashCode 方法。這是因爲在 Java 中,對象的 hashCode 值用於在哈希表(Hash Table)等數據結構中進行快速查找,而哈希表的實現原理是根據對象的 hashCode 值進行散列(Hash),所以如果兩個對象的 equals 方法返回 true,則它們的 hashCode 值也必須相等,否則可能會導致哈希表的查詢等操作出現錯誤結果。

以下是一個示例,演示了爲什麼需要同時重寫 equalshashCode 方法:

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 = 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 對象的兩個屬性 nameage 是否相等,如果相等則返回相同的 hashCode 值。

需要注意的是,這裏的 31 是一個質數,它的作用是爲了避免哈希衝突,因爲 31 的乘法運算比較快,而且相對來說能夠更加均勻地散佈哈希值,從而減少哈希衝突的發生。

重寫了 hashCode 方法之後,就可以保證在哈希表等數據結構中,同一個對象的 hashCode 值不變,不同對象的 hashCode 值不同,從而能夠正確地進行查找和比較操作。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章