JavaRush /Java Blog /Random-JA /Javaでのequals()メソッドとhashCode()メソッドのオーバーロード
Coder
レベル 17

Javaでのequals()メソッドとhashCode()メソッドのオーバーロード

Random-JA グループに公開済み

Javaでのequals()メソッドとhashCode()メソッドのオーバーライド

Equalsおよび は、hashCodeクラス内で宣言されObject、標準 Java ライブラリに含まれる基本的なメソッドです。 Java でのquals() メソッドと hashCode() メソッドのオーバーロード - 1このメソッドは、オブジェクトを比較し、オブジェクトの整数コードを生成するためеquals()に使用されます。hashCodeこれらのメソッドは、 にオブジェクトを挿入および取得するときに Java 標準ライブラリで広く使用されていますHashMap。このメソッドは、一意のオブジェクトのみが他の実装equalに格納されるようにするためや、オブジェクトを比較する必要があるその他の場合にも使用されます。クラス内のメソッドのデフォルト実装は、変数が格納するメモリ アドレスへの参照を比較し、アドレスが一致する場合、つまり変数が同じオブジェクトを参照する場合にのみ返します。Java では、比較が自然なロジックまたはビジネス ロジックに従うことが予想される場合、およびメソッドをオーバーライドすることをお勧めします。標準 Java ライブラリの多くのクラスはこれらをオーバーライドします。たとえば、このクラスは、比較される 2 つのオブジェクトの内容が同じである場合に返すようにオーバーライドします。ラッパー クラスはメソッドをオーバーライドして数値比較などを実行します。Java はとメソッドにも依存してと を比較するため、Java はこれらのメソッドをオーバーライドするための次のルールを提供します。 HashSetSetequals()java.lang.Objecttrueequals()hashCode()StringequalstrueIntegerequalHashMapHashTableequals()hashCode()keyvalues
  1. 反射性: オブジェクトはそれ自体と等しくなければなりません。
  2. 対称:a.equals(b)を返す場合はtrue、 もb.equals(a)返さなければなりませんtrue
  3. 推移性:a.equals(b)を返しtrueb.equals(c)さらに を返す場合はtruec.equals(a)も返さなければなりませんtrue
  4. 一貫性: メソッドの繰り返し呼び出しは、equals()オブジェクトのプロパティ値の一部が変更されない限り、同じ値を返す必要があります。つまり、Java で 2 つのオブジェクトが等しい場合、それらのプロパティが変更されない限り、それらは等しいことになります。
  5. 比較null: オブジェクトをチェックする必要がありますnull。オブジェクトが に等しい場合null、メソッドはfalseではなくを返す必要がありますNullPointerException。たとえば、a.equals(null)を返す必要がありますfalse

JavaにおけるequalsとhashCodeの間の合意

  1. メソッドの実行結果においてオブジェクトが等しい場合equals、それらはhashcode同じである必要があります。
  2. メソッドの実行結果においてオブジェクトが等しくない場合equals、それらはhashcode同じであることも、異なることもあり得ます。ただし、パフォーマンスを向上させるには、異なるオブジェクトが異なるコードを返すようにすることをお勧めします。

Javaでequalsメソッドをオーバーライドする方法

  1. @Override
    public boolean equals(Object obj) {
    /*1. Check*/if (obj == this) {
    /*and return */ return true;
             }
  2. オブジェクトに があるかどうかを確認しnull、オブジェクトが同じタイプであることも確認してください。instanceofこれはサブクラスに対して返されtrue、クラスが として宣言されている場合にのみ正しく動作するため、 をチェックしないでくださいimmutablegetClass();を使用できます。

    if (obj == null || obj.getClass() != this.getClass()) {
                return false;
    }
  3. 比較する型の変数を宣言し、objその型にキャストします。次に、数値属性の方がより速くチェックされるため、数値属性 (存在する場合) から始めて各タイプ属性を比較します。AND 演算子と OR 演算子 ( と呼ばれるshort-circuit logical operators) を使用して属性を比較し、チェックを他の属性と組み合わせます。

    Person guest = (Person) obj;
            return id == guest.id && (firstName == guest.firstName ||
                (firstName != null && firstName.equals(guest.getFirstName())))
                    && (lastName == guest.lastName || (lastName != null &&                      lastName .equals(guest.getLastName())));
    }
Javaでequalsメソッドをオーバーライドする完全な例
/** * Person class with equals and hashcode implementation in Java * @author Javin Paul */
public class Person {
    private int id;
    private String firstName;
    private String lastName;

    public int getId() { return id; }
    public void setId(int id) { this.id = id;}

    public String getFirstName() { return firstName; }
    public void setFirstName(String firstName) { this.firstName = firstName; }
    public String getLastName() { return lastName; }
    public void setLastName(String lastName) { this.lastName = lastName; }
    @Override
    public boolean equals(Object obj) {
    if (obj == this) {
        return true;
    }
    if (obj == null || obj.getClass() != this.getClass()) {
        return false;
    }

    Person guest = (Person) obj;
    return id == guest.id
        && (firstName == guest.firstName
            || (firstName != null &&firstName.equals(guest.getFirstName())))        && (lastName == guest.lastName
            || (lastName != null && lastName .equals(guest.getLastName())
            ));
    }
    @Override
    public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());             result = prime * result + id; result = prime * result +
        ((lastName == null) ? 0 : lastName.hashCode()); return result;
    }
 }

Javaでequalsをオーバーライドする際のよくある間違い

  1. クラス内のメソッドの構文は次のように定義されていますが、多くのプログラマーは、クラスの名前を引数として使用する代わりに(例: Person) 、誤ってメソッドをオーバーロードしてequals (Override)しまいます。このエラーは、 により検出が困難です。したがって、クラスのオブジェクトに対してこのメ​​ソッドを呼び出すと、メソッドはコンパイルされるだけでなく、正しくコンパイルされます。ただし、たとえばオブジェクトをコレクションに入れ、その操作がメソッドに基づいているメソッドを呼び出す場合、そのメソッドはオブジェクトを検出できません。(Overload)equals()Objectpublic boolean equals(Object obj)public boolean equals(Person obj)Objectstatic bindingArrayListcontains()equals()contains

  2. メソッドをオーバーライドするときは、変数equals()をチェックしないでください。最終的には を呼び出すときにチェックされます。以下は正しいコードです。nullNullPointerExceptionequals()

    firstname == guest.firstname || (firstname != null &&
         firstname.equals(guest.firstname));
  3. 3 番目のよくある間違いは、メソッドをオーバーライドせずhashCode()equals(). Java でもequals()両方のメソッドをオーバーライドする必要があります。hashCode()このメソッドは-collections (たとえば、 )hashCodeで使用され、衝突が少ないほど (異なるオブジェクトに同じコードが使用されるほど)、これらのコレクションはクラスのオブジェクトでより効率的に機能します。hashHashSet

  4. プログラマが犯す最後のよくある間違いは、メソッドをオーバーライドするときに、equals()メソッドequals()とメソッド間のマッピングが保持されないことですcompareTo()。これは、 に重複を格納することを避けるための非公式の要件ですSet (SortedSet, TreeSet)

Javaでequalsメソッドを記述する方法のヒント

  1. NetBeans、Eclipse、IntelliJ IDEA などのほとんどの IDE は、メソッドequals()との生成をサポートしていますhashCode()。Eclipse では、右クリック -> ソース ->generate equals()と を選択しますhashCode()

  2. クラスに一意のビジネス キーがある場合は、これらのフィールドが等しいかどうかだけをチェックするだけで十分です。この例のように、「id」は各人に固有の番号です。

  3. Java でオーバーライドする場合はhashCode()、メソッドで使用されたすべてのフィールドを必ず使用してくださいequals()

  4. Stringおよび などのラッパー クラスはIntegerメソッドをオーバーライドしますFloatが、オーバーライドしません。Doubleequals()StringBuffer

  5. 可能な限り、Java の変数immutableを使用してフィールドを作成します。final

  6. オブジェクトを比較する場合はStringequals()代わりに . 演算子を使用します==

  7. 論理的には等しいが、異なるオブジェクトからロードされた 2 つのオブジェクトはClassLoader等しくありません。ローダークラスが異なる場合は、 でチェックすると結果getClass()が返されることに注意してください。false

  8. @Override. メソッドでもアノテーションを使用するhashCodeと、 の戻り値などの微妙なエラーが防止されますint。ただし、一部のプログラマは . を返しますlong

PS 親愛なる同僚の皆様!この記事はレベル 21 の問題を解決するのに役立ちました。このトピックの分析に成功することを願っています。翻訳を使用してください。今ではこのフォーラムにコメントを残すこともできないので、評価を上げるのにご協力いただければ幸いです。皆さん、本当にありがとうございました! 元の記事 時間がなかったので一部省略しましたが、レベル21の問題を解くために知っておくべきことをすべて翻訳しました。
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION