クラスcompareTo()と矛盾する場合、誰かが結果を明らかにすることができますか。であることが必須ではない場合、それequals()を読んだことがあります。しかし、これが起こった場合の結果はどうなりますか。ありがとう。Obj1.compareTo(Obj2) = 0Obj1.equals(Obj2) = true
3 に答える
のドキュメントでComparableは、これについて詳しく説明しています。
クラスの自然な順序付けは、クラスのすべてのおよびクラスと同じブール値を持つ場合にのみ、
C一貫性があると言われます。はどのクラスのインスタンスでもないことに注意してください。equalse1.compareTo(e2) == 0e1.equals(e2)e1e2Cnulle.compareTo(null)NullPointerExceptione.equals(null)false自然な順序付けが と一致することを強くお勧めします (必須ではありません)
equals。これは、明示的な比較子のないソートされたセット (およびソートされたマップ) が、自然な順序付けが と一致しない要素 (またはキー) で使用されると、「奇妙な」動作をするためequalsです。特に、そのようなソートされたセット (またはソートされたマップ) は、メソッドに関して定義されているセット (またはマップ) の一般的な規約に違反していequalsます。たとえば、明示的なコンパレータを使用しないソート済みセットに 2 つのキー を追加すると、2 番目の追加操作が返されます
a(ソート済みセットのサイズは増加しません) 。b(!a.equals(b) && a.compareTo(b) == 0)falseabを実装する事実上すべての Java コア クラス
Comparableは、equals. 1 つの例外はjava.math.BigDecimalで、その自然な順序付けでは、BigDecimal値が等しく精度が異なるオブジェクト ( と など4.0)が同等と見なされます4.00。
ドキュメントには一貫性は必須ではないと書かれていますが、オブジェクトがいつかTreeMap/などに存在するかどうかわからないため、常にこの一貫性を確保することをお勧めしますTreeSet。compareTo()等しくない 2 つのオブジェクトに対して 0 を返す場合、すべてのツリー ベースのコレクションが壊れています。
たとえば、Query2 つのフィールドを持つ SQL クエリを実装するclass を想像してください。
- tableList: テーブルのリスト
- 参照: そのようなクエリを使用するプログラムのリスト
tableList が等しい場合、つまりtableListがこのオブジェクトの自然キーである場合、2 つのオブジェクトは等しいとします。hashCode()フィールドequals()のみを考慮しますtableList:
public class Query implements Comparable {
List<String> tableList;
List<String> references;
Query(List<String> tableList, List<String> references) {
this.tableList = tableList;
this.references = references;
Collections.sort(tableList); // normalize
}
@Override
public int hashCode() {
int hash = 5;
hash = 53 * hash + Objects.hashCode(this.tableList);
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Query other = (Query) obj;
return Objects.equals(this.tableList, other.tableList);
}
}
並べ替えを参照の数に沿って行いたいとしましょう。コードを素朴に書くと、次のcompareTo()ようなメソッドが生成されます。
public int compareTo(Object o) {
Query other = (Query) o;
int s1 = references.size();
int s2 = other.references.size();
if (s1 == s2) {
return 0;
}
return s1 - s2;
}
等価性とソートは 2 つの別々のフィールドで行われるため、これまでのところ問題ないようです。
ただし、 が aTreeSetまたは aTreeMapに置かれると、壊滅的です。これらのクラスの実装では、compareTo が 0 を返す場合、要素が等しいと見なされます。この場合、同じ数の参照を持つ各オブジェクトは実際には「等しい」オブジェクトであることを意味しますが、明らかにそうではありません。
より良いcompareTo()方法は次のとおりです。
public int compareTo(Object o) {
Query other = (Query) o;
// important to match equals!!!
if (this.equals(other)) {
return 0;
}
int s1 = references.size();
int s2 = other.references.size();
if (s1 == s2) {
return -1; // not 0, they are NOT equal!
}
return s1 - s2;
}
一部のコレクションは、2 つのオブジェクトが続く場合も true であると想定しobj1.compareTo(obj2) = 0ますobj1.equals(obj2)。例TreeSet: このロジックを満たさないと、iconsistent コレクションが発生します。参照:
コンパレータと equals()。