equalsを使用してequalsメソッドを書き換えるときに、hashCodeを書き換える必要があるのはなぜですか?

1.等しいの使用

2つのオブジェクトが等しいかどうかを判断するために使用されます。

  • クラスがObjectのequalsメソッドをオーバーライドしない場合は、Objectのequalsメソッドを呼び出して、ヒープ内のオブジェクトのアドレスが等しいかどうかを比較します。
  • クラスがequalsメソッドをオーバーライドする場合、通常、オブジェクトのプロパティが等しいかどうかを比較するために使用されます
2.なぜ書き換えが等しいのですか?

なぜequalsメソッドを書き直すのですか?これは主に使用シナリオに依存します。オブジェクトを比較する必要がない場合は、書き直す必要はありません。
たとえば、ユーザーがユーザー名を変更したい場合、Userオブジェクトが渡されます。このとき、古いUserオブジェクトがDBから取得され、2つが等しいかどうか(実際にはユーザー名)が比較されます。 equalsメソッドが書き直されていない場合は、Objectのequalsメソッドを使用してオブジェクトのアドレスを比較しますが、これは私たちの希望に反します。

例1

public class Main {
    
    
    public static void main(String[] args) {
    
    
        User newUser = new User("dkangel");
        User dbUser = new User("dkangel");
        System.out.println(newUser.equals(dbUser));
    }
}

1. equalsメソッドはオーバーライドされず、結果はfalseになります

public class User {
    
    
    private String name;
    
    public User(String name) {
    
    
        this.name = name;
    }
    
    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }
}

2. equalsメソッドをオーバーライドすると、結果はtrueになります

public class User {
    
    
    private String name;

    public User(String name) {
    
    
        this.name = name;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    /**
     * 重写equals方法,比较name属性是否相等
     *
     * @param obj 待比较对象
     * @return boolean
     */
    @Override
    public boolean equals(Object obj) {
    
    
        if (this == obj) {
    
    
            return true;
        }
        if (!(obj instanceof User)) {
    
    
            return false;
        }
        User user = (User) obj;
        return Objects.equals(user.name, this.getName());
    }
}
3. equalsメソッドを書き直すには、hashCodeメソッドを書き直す必要がありますか?どうして?

hashCodeメソッドの機能は、ハッシュコード(ハッシュコードとも呼ばれます)を取得することであり、ハッシュコードの機能は、ハッシュテーブル内のオブジェクトの位置を決定することです。

まず、hashCodeとequalsの関連する規定を見てください。

  • 2つのオブジェクトが等しい場合、ハッシュコードも同じである必要があります
  • 2つのオブジェクトは等しく、2つのオブジェクトのequalsメソッドはそれぞれtrueを返します
  • 2つのオブジェクトは同じハッシュコード値を持ち、必ずしも等しいとは限りません
  • hashCodeメソッドのデフォルトの動作は、ヒープ上のオブジェクトに対して一意の値を生成することです。hashCodeメソッドがオーバーライドされない場合、このクラスの2つのオブジェクトはとにかく等しくなりません(2つのオブジェクトが同じデータを指している場合でも)

慣例の観点から:equalsメソッドを書き直すには、hashCodeメソッドを書き直す必要があります。

使用の観点から:

  • クラスが使用中にクラスに対応するハッシュテーブルを作成する必要がない場合(つまり、HashMap / HashSet / HashTableなどのハッシュを使用するデータデータでは使用されない場合)、クラスはhashCodeメソッドであり、hashCodeメソッドを書き直す必要はありません。上記の例1のように、equalsメソッドのみが書き換えられ、hashCodeメソッドは書き換えられないため、使用に影響はありません。

  • クラスが使用中にクラスに対応するハッシュテーブルを作成する必要がある場合は、hashCodeメソッドを書き直す必要があります。なぜですか。別の栗を与える

例2

HashSetにオブジェクトを追加すると、HashSetは最初にオブジェクトのハッシュコード値を計算してオブジェクトが追加された位置を決定し、その位置に追加された他のオブジェクトのハッシュコード値と比較します。一致するものがない場合ハッシュコードの場合、HashSetはオブジェクトを繰り返しなしと見なします。ただし、同じハッシュコード値を持つオブジェクトが見つかった場合は、equals()メソッドが呼び出され、等しいハッシュコードを持つオブジェクトが実際に同じであるかどうかがチェックされます。2つが同じである場合、HashSetは操作に正常に参加させません。それらが異なる場合、それらは別の場所に再ハッシュされます。

public class Main {
    
    
    public static void main(String[] args) {
    
    
        User newUser = new User("dkangel");
        User dbUser = new User("dkangel");
        User otherUser = new User("zhangsan");

        HashSet<User> users = new HashSet();
        users.add(newUser);
        users.add(dbUser);
        users.add(otherUser);

        System.out.println("users size: " + users.size());
        users.forEach(user -> System.out.printf("name: %s, hashCode: %s\n", user.getName(), user.hashCode()));
    }
}

1. hashCodeメソッドは書き換えられておらず
结果为3、名前が「dkangel」である2つのオブジェクトはhashCodeメソッドを書き換えていないため、セット内の値が重複しています。
ここに画像の説明を挿入
2.hashCodeメソッドを書き直します

public class User {
    
    
    private String name;

    public User(String name) {
    
    
        this.name = name;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    @Override
    public boolean equals(Object obj) {
    
    
        if (this == obj) {
    
    
            return true;
        }
        if (!(obj instanceof User)) {
    
    
            return false;
        }
        User user = (User) obj;
        return Objects.equals(user.name, this.getName());
    }

    @Override
    public int hashCode() {
    
    
        return this.name.hashCode();
    }
}

结果为2、hashCodeメソッドを書き直します。「dkangel」という名前の2つのオブジェクトは、セットに1つだけ追加します。
ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/Dkangel/article/details/105980473