2

モデルと価格の 2 つの値を含む Java Bean Car があります。

ここで、その方法でモデルのみをチェックする equals() と hashcode() をオーバーライドするとします。

public boolean equals(Object o) {            
    return this.model.equals(o.model);
}


public int hashCode() {
    return model.hashCode();
}

これにより、配列リストに同じモデルの項目 Car が既に含まれているかどうかを確認できます (価格は関係ありません)。

List<Car> car = new ArrayList<Car>();


car.add(new Car("carA",100f));
car.add(new Car("carB",101f));
car.add(new Car("carC",110f));

System.out.println(a.contains(new Car("carB",111f)));

TRUE を返します。車はすでにあるので大丈夫です!

しかし、注文した項目を維持したいので、ArrayList は良くないと判断したので、次のように TreeSet に置き換えます。

Set<Car> car = new TreeSet<Car>(new Comparator<Car>() {
@Override 
public int compare(Car car1, Car car2) {

    int compPrice = - Float.compare(car1.getPrice(), car2.getPrice());

    if (compPrice > 0 || compPrice < 0)
        return compPrice;
    else
        return car1.getModel().compareTo(car2.getModel());                                  

}});

car.add(new Car("carA",100f));
car.add(new Car("carB",101f));
car.add(new Car("carC",110f));

System.out.println(a.contains(new Car("carB",111f)));

しかし、問題があり、FALSE が返されます...なぜですか?

arrayList を使用して contains() を呼び出すと、 equals() メソッドが呼び出されるようです。しかし、コンパレータで TreeSet を使用して contains() を呼び出すと、代わりにコンパレータが使用されるようです。

なぜそれが起こるのですか?

4

3 に答える 3

3

ATreeSetは暗黙的にソートされ、Comparatorこのソートには a を使用します。このequals()メソッドは、2 つのオブジェクトが同じか異なるかのみを示し、並べ替えの順序は示しません。それができるのはAだけComparatorです。

さらに重要なことに、 aは検索TreeSetにも比較を使用します。これは、ツリーベースのマップ/セットの要点のようなものです。メソッドが呼び出されると、バイナリ検索が実行され、コンパレータの定義方法に基づいて、ターゲットが見つかるかどうかが判断されます。比較演算子は、論理順序だけでなく、論理 ID も定義します。一貫性のない実装によって定義された論理 ID に依存している場合、混乱が生じる可能性があります。contains()equals()

于 2012-12-07T00:38:42.093 に答える
3

TreeSetは自然な (またはそうでない) 順序に従って要素を保持するバイナリ ツリーを形成するため、特定の 1 つの要素をコレクションですばやく検索するには、 の代わりにorをTreeSet使用します。ComparableComparatorequals()

TreeSet JavaDoc が正確に示すように:

Set インタフェースを正しく実装するためには、(明示的なコンパレータが提供されているかどうかに関係なく) セットによって維持される順序付けが equals と一致している必要があることに注意してください。(equals との整合性の正確な定義については、Comparable または Comparator を参照してください。) これは、Set インターフェースが equals 操作に関して定義されているためですが、TreeSet インスタンスはその compareTo (または比較) メソッドを使用してすべての要素の比較を実行するためです。この方法で等しいと見なされる要素は、セットの観点からは等しいです。セットの動作は、その順序付けが equals と一致しない場合でも明確に定義されています。Set インターフェースの一般的な契約に従わないだけです。

HashCode/Equals コントラクトとの類似点を見つけることができます。

equals()返す場合true、検索中に見つかるためには true も返さなければなりません。hashcode()

同様にTreeSet

contains()(Comparatorまたはを使用してComparable) が返す場合true、と一貫性を保つためにも返さなければなりません。equals() trueequals()

THEREFORE:メソッド内で使用されるフィールドはTreeSet.equals()、実装内とまったく同じ (それ以上でも以下でもない) である必要がありますComparator

于 2012-12-07T01:09:45.100 に答える
0

動作が異なる理由は、compare メソッドで price メンバーを考慮し、equals でそれを無視するためです。

new Car("carB",101f)     // what you add to the list   
new Car("carB",111f)     // what you are looking for

モデルメンバーが等しいため、両方のインスタンスは「等しい」(申し訳ありません...)(そして、そのテストの後に実装が停止します)。ただし、その実装は価格メンバーもチェックするため、それらは異なるものとして「比較」します。

于 2012-12-07T00:54:32.847 に答える