2

イコールとハッシュコードに関して疑問があります。私が以前に理解したことは、そのクラスがコレクションクラスまたはMapクラスに追加されることになっている場合、オブジェクトクラスのhashcode()およびequals()メソッドをオーバーライドする必要があるということです。以下の例をご覧ください。ハッシュコードとequalsメソッドをオーバーライドしませんでした。それでも私は私が望むものを望む結果を得る。私が理解したことの1つは、2つのオブジェクトを比較する場合は、equalsメソッドをオーバーライドする必要があるということです。ただし、この例では、2つのオブジェクトを比較しているのではなく、ハッシュコードとequalsをオーバーライドせずに、コレクションまたはマップにオブジェクトを追加しています。ハッシュコードをオーバーライドする必要がある理由と時期を誰かが説明できますか?

package equalshashcode;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class EqualsAndHashCode {
    public static void main(String[] args) {
        Student student1 = new Student("A");
        Student student2 = new Student("B");

        List<Student> studentList = new ArrayList<Student>();

        Map<Integer,Student> studentMap = new HashMap<Integer,Student>();

        studentMap.put(1, student1);
        studentMap.put(2, student2);

        studentList.add(student1);
        studentList.add(student2);

        System.out.println("Student HashMap:: "+studentMap.get(1));
        System.out.println("Before removing::"+studentList);
        System.out.println(studentList.remove(student1));//true success
        System.out.println("After removing::"+studentList);
    }
}

class Student{

    String name;
    public Student(String pName){
        this.name = pName ;
    }

    public String getName(){
        return this.name ;
    }
}
4

3 に答える 3

4

コレクションに要素を実装equals()して追加する必要は必ずしもありません。hashCode()

List(インスタンスstudentListであるあなたなどArrayList)の場合、ほとんどのアクションでは問題になりません。

あなたが必要 equals()としhashCode()、オブジェクトの「平等」が関係する唯一の場所です。そして、それらの場所でさえ、デフォルトの実装で十分かもしれません。

平等は、いくつかの場合に重要です。たとえば、次のようになります。

  • Set互いに等しい2つのオブジェクトを含めることはできません
  • aのキーは、取得可能でMapあるために正しいequals()実装を持っている必要があります(そして、具体的な実装に基づいて、それも正しく実装されなければならMapないことを意味するかもしれませんhashCode())。
  • 「通常」のメソッドの中には、List同等性が必要なものもあります。たとえばcontains()、正しく実装する必要がありindexOf()ます/remove(Object)equals()hashCode()
于 2012-08-20T12:09:43.393 に答える
1

カスタムequalshashCodeメソッドは、通常、実際の同等性を判断するために使用されます。デフォルトの方法に依存している場合equals、これはメモリ内で同じインスタンスを探します。たとえばcustomObj1.equals(customObj2)、カスタムequalsメソッドがなく、2 つのオブジェクトが別々の (しかしそれ以外は等しい) インスタンスである場合、 false が返されます。カスタムequalsメソッドの考え方は、同じ例が実際に等しい場合に true を返すようにすることです。次にMap、これを使用して、リクエストで渡されたキー オブジェクトを照合し、キーget(key)の正しいインスタンスを持たなくても値を見つけることができます (a はHashMap実際にhashCodeこれを行うために使用します)。

これが有用であることの最も明らかな例はStrings です。これにより、キー インスタンスが( implementsおよびfor you) にmyMap.get("key")格納されているものと同じでなくても、正しい値を実行して取得できます。一般に、これらの Java 組み込みおよびメソッドを使用して独自のものを構築することをお勧めします。たとえば、オブジェクトに などの自然な ID がある場合、このバージョンを使用して独自の equals を完成させることができます (明らかに複数のフィールドを比較できます)。MapStringequalshashCodeequalshashCodeuserNameequalsString

public boolean equals(Object o) {
    if (o instanceof MyObj) {
        return userName.equals(((MyObj) o).userName));
    }
    return false;
}

そのため、単一Threadの 、または制限された変数のみを使用する場合、これらのメソッドを実装する必要はおそらくないでしょう。

于 2012-08-20T12:23:10.443 に答える
0

コレクションクラスは、デフォルトのequals / hashCode実装を持つオブジェクトで完全に機能します。このため、独自のクラスを追加する必要はありません。

カスタムのequals/hashCodeメソッドは間違えやすいので、自分でロールする正当な理由がない限り、java.lang.Objectで無料で入手できるメソッドをそのまま使用する必要があります。

これらのメソッドの独自のバージョンを作成する最も一般的な理由は、同じクラスの2つの別々のインスタンスを等しいものとして扱いたい場合です。たとえば、Accountクラスがあり、同じaccountNumberプロパティを持つAccountの2つのインスタンスが同じ実世界のアカウントを表すため、それらが等しいと見なされるようにしたい場合です。この場合、equalsメソッドはaccountNumberの値のみに基づいており、カスタムのequalsメソッドがあるため、equals / hashCodeコントラクトを満たすために、hashCodeの適切な実装も提供する必要があります。

于 2012-08-20T12:10:07.377 に答える