私は、JavaのCollections
の契約に準拠するために(予期しない動作を避けるために)、Comparator
はequalsと一貫している必要があることを知っています。コンパレータと等価と一致:どのように?
私はこのような者があるとします。
class Person {
private String name;
private String surname;
private int age;
public Person(String name, String surname, int age) {
this.name = name;
this.surname = surname;
this.age = age;
}
public String getName() { return name; }
public String getSurname() { return surname; }
public int getAge() { return age; }
}
コンパレータは、そのComparator
を使用して、
class PersonComparator implements Comparator<Person> {
@Override
public int compareTo(Person p1, Person p2) {
// throws NPE's
return p1.getName().compareTo(p2.getName());
}
}
今、私はいくつかのソートされたコレクション(TreeMap
、SortedSet
、...何を)したいだろうPerson
の名前のみを比較します。 このコンパレータは、 "equal with equals"契約に違反します。しかし、私はequals(Object o)
を無効にしたくありません。プログラムの他の部分では、同じ名前、姓、年齢の2人の人が(実際の人と同じように)異なる可能性があるからです。
選択したコレクションに名前がPersonを一意に識別したい、つまりTreeSet<Person>
に「John Doe」と「John Smith」(同じ名前)を使用できないようにします。
これは、私がそれらをテストした限り、Java Collectionsの現在の実装でうまくいきます。
私の質問は:どのように契約を壊すことなく理想的にこれを「正しく」行うのですか?可能であれば、私は第三者図書館を避けたいと思います。もちろん、契約を解消するためにデータ構造を自分で実装したくありません。 私の懸念は、契約に違反するため、将来のJavaリリースでコードが壊れる可能性があることです。
「Comparator」は、equalsと一致する必要はありません。それは一般的ですが、ではなくが厳密に必要です。 ((x、y)== 0と比較)==(x.equals(y))。一般的に言えば、 この条件に違反するコンパレータは、この事実を明確に示すはずです( )。推奨される言語は "Note:この比較器 はequalsと矛盾する順序を課します。" – Eran
Personクラスのすべてのデータが人を明確に識別できない場合は、モデルが不十分である可能性があります。最終的には、_same_人を表すための複数の 'Person'インスタンスがある状況に遭遇します。だから私はいくつかの一意の識別子を追加して、あなたのコンパレータと同様に 'equals()'でそれを使うことを提案したいと思います。 – Thomas
@Thomas「モデルが不十分であるかもしれないことを示している」 - ありがとう、私はそれが良い点だと思う。 (私の実際のユースケースはかなり異なっていますが、その点はまだ当てはまるかもしれません...) – Moritz