2

こんにちは、私はJavaを初めて使用します。セットコレクションが重複しないことを知っており、要素がコレクションに既に存在する場合、そのcontainsメソッドはtrueを返す必要があります。以下のプログラムを実行しようとしていますが、予期しない結果が得られます。

public class UserDefinedName {
    private final String first, last;

    public UserDefinedName(String first, String last) {
        this.first = first;
        this.last = last;
    }

    public boolean equals(Object o) {
        if (!(o instanceof UserDefinedName))
            return false;
        UserDefinedName n = (UserDefinedName) o;
        return n.first.equals(first) && n.last.equals(last);
    }

    public static void main(String[] args) {
        Set<UserDefinedName> s = new HashSet<UserDefinedName>();
        s.add(new UserDefinedName("Carballo", "Videl"));
        System.out.println(s.contains(new UserDefinedName("Carballo", "Videl")));
    }
}

出力trueを期待していますが、プログラムはfalseを出力します。私は何を間違っていますか?

4

5 に答える 5

8

フォーム Javaドキュメント

equals(Object) メソッドに従って 2 つのオブジェクトが等しい場合、2 つのオブジェクトのそれぞれで hashCode メソッドを呼び出すと、同じ整数結果が生成される必要があります。

hashCode() メソッドがオーバーライドされていない場合、デフォルトの実装である Object の hashCode() メソッドが使用されます。

あなたの場合、 equals メソッドをオーバーライドしていますが、 UserDefinedName クラスで hashCode() メソッドをオーバーライドしなかったため、 hashCode() のデフォルトの実装を使用します。

UserDefinedName クラスは equals メソッドをオーバーライドし、hashCode コントラクトは、等しいオブジェクトが等しいハッシュ コードを持つことを要求します。この契約を満たすには、 equals をオーバーライドするたびに hashCode をオーバーライドする必要があります

次のコードを追加すると動作します。

public int hashCode() {
return 37 * first.hashCode() + last.hashCode(); 
}
于 2013-06-14T08:49:53.767 に答える
1

equals メソッドをオーバーライドする場合は、常に hashcode メソッドもオーバーライドします。簡単なルールは、2 つのオブジェクトが等しいと見なされる場合、同じハッシュコードを返す必要があるということです。

私はあなたのコードを取り、Eclipseの助けを借りてequalsとhashcodeを生成しました

import java.util.HashSet;
import java.util.Set;

public class UserDefinedName {
private final String first, last;

public UserDefinedName(String first, String last) {
    this.first = first;
    this.last = last;
}

public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((first == null) ? 0 : first.hashCode());
    result = prime * result + ((last == null) ? 0 : last.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    UserDefinedName other = (UserDefinedName) obj;
    if (first == null) {
        if (other.first != null)
            return false;
    } else if (!first.equals(other.first))
        return false;
    if (last == null) {
        if (other.last != null)
            return false;
    } else if (!last.equals(other.last))
        return false;
    return true;
}

public static void main(String[] args) {
    Set<UserDefinedName> s = new HashSet<UserDefinedName>();
    s.add(new UserDefinedName("Carballo", "Videl"));
    System.out.println(s.contains(new UserDefinedName("Carballo", "Videl")));
    UserDefinedName obj1 = new UserDefinedName("prasad", "kharkar");
    UserDefinedName obj2 = new UserDefinedName("prasad", "kharkar");

    System.out.println(obj1.equals(obj2));
    System.out.println(obj1.hashCode());
    System.out.println(obj2.hashCode());

    }
}

出力は

true
true
-1072813416
-1072813416
于 2013-06-14T08:48:46.300 に答える
1

オブジェクトのhashSetハッシュコード値を使用して格納するためです。したがって、独自のクラスでメソッド hashCode をオーバーライドする必要があります。オーバーライドしなかったため、オブジェクト クラスから継承された hashCode メソッドを使用します。

オブジェクト クラスからのハッシュコードは、オブジェクトのメモリ アドレスを使用して計算されます。つまり、次のようになります。

UserDefinedName p = new UserDefinedName("Carballo", "Videl");
System.out.println(p);
System.out.println(0x1e5e2c3);
System.out.println(p.hashCode());

出力:

UserDefinedName@1e5e2c3
31843011
31843011

したがって、これを試してみると、 true が出力されることがわかります。

Set<UserDefinedName> s = new HashSet<UserDefinedName>();
UserDefinedName p = new UserDefinedName("Carballo", "Videl");
s.add(p);
System.out.println(s.contains(p));

ユーザークラスの正確さを比較したい場合は、hashCodeメソッドをオーバーライドして(Eclipseで生成できます)、hashCodeフィールドごとにオブジェクトを生成する必要があります。

クラスにこのメソッドがある場合、これは提供するコードに対して true を出力します。

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((first == null) ? 0 : first.hashCode());
        result = prime * result + ((last == null) ? 0 : last.hashCode());
        return result;
    }
于 2013-06-14T08:37:11.980 に答える