2

特定の順序で並べ替えたいクラスのインスタンスがありますが、別の基準を使用してインスタンスがセットに存在するかどうかを確認することもできます。例:

public class Foo {
    int x;
    int y;

    public Foo(int x, int y) { this.x = x; this.y = y }

    // equality determined by value of 'x':
    @Override 
    public boolean equals(Object obj) {
        if (obj instanceof Foo) {
            return ((Foo)obj).x == this.x;
        }
        return false;
    }

    @Override
    public int hashCode() {
        return this.x;
    }

    @Override
    public int compareTo(Foo foo) {
        if (this.x < foo.x return -1;
        else if (this.x > foo.x return 1;
        return 0;
    }
}

...

// Would like to keep a set of Foos, but sorted by 'y' value.
// Passing in an explicit comparator which sorts on 'y'.
SortedSet<Foo> test = new TreeSet<Foo>(new ComparatorFoo());

public static class ComparatorFoo implements Comparator<Foo> {
    @Override
    public int compare(Foo o1, Foo o2) {
        if (o1.y < o2.y) return -1;
        else if (o1.y > o2.y) return 1;
        return 0;
    }
}

今しようとしている:

test.add(new Foo(3, 4));
test.add(new Foo(1, 2));
test.add(new Foo(5, 6));

// sorts by 'y' ok.
for (Foo foo : test) {
    System.out.println(foo.toString());
}

// but can't find an instance with the same 'x' value:
test.contains(new Foo(1, 999));

これを行うには、2 つの別個のデータ構造を保持する必要がありますか? (1 つはソート用、もう 1 つは等価テスト用?)

ありがとうございました

- - - アップデート - - - - -

最終結果: SortedSet の初期化に使用されるコンパレーターは、contains() が呼び出されたときにも使用されます。したがって、セットを「y」でソートして、「x」で要素の存在をチェックすることはできませんでした。

4

1 に答える 1

4

compareTo一貫性を定義する必要がありますequals

SortedSet強調表示された部分を確認するJavaドキュメントから。

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

以下のようにコンパレータを変更します

public static class ComparatorFoo implements Comparator<Foo> {
    @Override
    public int compare(Foo o1, Foo o2) {
        if (o1.x < o2.x)
            return -1;
        else if (o1.x > o2.x)
            return 1;
        return 0;
    }
}

それはあなたを返しますtrue

于 2012-10-30T17:57:31.917 に答える