5

この質問は確かに新しいものではありませんが、役立つ答えはどこにも見つかりませんでした。

以下のコードでわかるように、equals メソッドと hashcode メソッドはオーバーライドされますが、それでも重複は許可されます。ハッシュコードは、Netbeans によって自動的に生成されています。

@Override
public boolean equals(Object o)
{
    TaskDetails other = (TaskDetails) o;
    if ( (id_subtask == other.id_subtask)
            && ((date.compareTo(other.date)) == 0) )
    {
        System.err.println("Duplicate Entry"+id_subtask+" + "+other.id_subtask);
        return true;
    }
    else
    {
        System.out.println("Good!" +id_subtask+" + "+other.id_subtask);
        return false;
    }

} 

@Override
public int hashCode() {
    int hash = 7;
    hash = 71 * hash + this.id_subtask;
    hash = 71 * hash + this.id_team_member;
    hash = 71 * hash + Float.floatToIntBits(this.nb_hours);
    hash = 71 * hash + (this.date != null ? this.date.hashCode() : 0);
    hash = 71 * hash + (this.comment != null ? this.comment.hashCode() : 0);
    hash = 71 * hash + (this.subtask_name != null ? this.subtask_name.hashCode() : 0);
    System.out.println("Hash : "+hash + "Subtask : " + id_subtask);
    return hash;       
}

これは、ハッシュセットにエントリを追加するために使用されるコードです。

TaskDetails newTaskDetails = new TaskDetails
                                (
                                    s.getId_subtask(),
                                    mus.teamMember.getId_team_member(),
                                    f,
                                    mysqlFormat.format(caldate),
                                    c.substring(0, Math.min(c.length(), 100)),
                                    s.getName_subtask()
                                );

                            allTasks.add(newTaskDetails);

(allTask​​s はハッシュセットです)

このコードは関数 A と B で使用されます。

関数 A のみを実行すると、正常に動作します。関数 A の後に関数 B が実行されると (したがって、上記のコードは 2 回実行されます)、重複するエントリがあることを示す system.err がトリガーされても、ハッシュセットは突然重複を受け入れますか?

コードに欠陥がありますか、それとも何か不足していますか?

助けてくれてありがとう!

4

5 に答える 5

8

2 つのオブジェクトを「等しい」と見なすために 2 つのフィールドを使用していますが、ハッシュコードを作成するために 2 つ以上のフィールドを使用しています。あなたのhashCode()方法は、あなたの方法よりも具体的であってはなりませんequals()。経験則として、hashCode()メソッドが使用しないフィールドは使用しないでくださいequals()(ただし、使用するフィールドは少なくてもかまいません)。より技術的に言えば、2 つのオブジェクトが「等しい」場合、それらは同じハッシュコードを持つ必要があります (逆は必要ありません)。

于 2012-12-10T15:31:21.090 に答える
3

hashCode() と equals() の間の一貫性要件に違反しています。equals() に従って 2 つのオブジェクトが等しい場合、同じハッシュも持つ必要があります。equals は 2 つのフィールドのみを考慮し、hashCode はそれ以上を考慮するため、この要件は満たされません。

于 2012-12-10T15:33:31.787 に答える
0

これは重複した質問です。以前の回答を参照してください。

が重複を許可する動作はjava.util.HashSet、 内のオブジェクトのハッシュ コードjava.util.HashSetが変更される可能性がある場合に発生します。

これは通常、オブジェクトのハッシュ コードが可変フィールドから構築されている場合に発生します。

于 2012-12-10T15:33:04.287 に答える
0

あなたの問題は、の実装がhashCode()一致しないことequals()です。どちらのメソッドも、オブジェクトの同じ属性を使用する必要があります。

が に評価されたとしても、実装ではhashCode()が異なる可能性があります。この場合 (異なる)、オブジェクトは で異なります。equals()truehashCodeHashMap

同じ属性を使用するように実装を修正してください。その後、エラーは消えるはずです。

于 2012-12-10T15:33:35.103 に答える
0

javadocからObject

If two objects are equal according to the equals(Object) method, then
calling the hashCode method on each of the two objects must produce the
same integer result. 

メソッドに応じて等しい 2 つのオブジェクトのハッシュコードが異なるequals(Object)ため、他のコードHashSetは間違った仮定を行い、間違った結果を返します。

一部のコードは、「コントラクト」を尊重する他のオブジェクトに依存するように記述されています。あなたのクラスはコントラクトを尊重しないため、コレクションではコントラクトが破られていないことがObject要求されるため、コレクション内の何も機能しないと想定できません。Object

于 2012-12-10T15:34:14.610 に答える