它写在所有体面的java课程中,如果你实现Comparable
接口,你应该(在大多数情况下)也覆盖equals
方法以匹配其行为
不幸的是,在我目前的组织中,人们试图说服我完全相反。我寻找最有说服力的代码示例向他们展示将要发生的所有邪恶。
答案 0 :(得分:5)
我认为你可以通过显示Comparable javadoc来表达:
强烈建议(尽管不要求)自然 排序与平等一致。这是因为排序集 没有明确的比较器的(和有序的地图)表现得很奇怪"奇怪的是#34;什么时候 它们与自然顺序的元素(或键)一起使用 与equals不一致。特别是,这样的排序集(或排序的 map)违反了定义的集合(或映射)的一般合同 就平等方法而言。
例如,如果添加两个键a和b使得(!a.equals(b)&& a.compareTo(b)== 0)到不使用显式的有序集 比较器,第二个add操作返回false(和大小 排序集不会增加)因为a和b是等价的 排序集的观点。
特别是对于SortedSet(和SortedMap),如果compareTo
方法返回0,它假定它相等,并且即使equals
方法返回false,也不会第二次添加该元素,并导致SortedSet javadoc
请注意由排序集维护的排序(无论是否为 提供显式比较器)如果必须与equals一致 排序集是为了正确实现Set接口。 (见 可比较的接口或Comparator接口,用于精确定义 与equals一致的。)这是因为Set接口是 根据equals操作定义,但是有序集合执行 所有元素比较使用compareTo(或compare)方法,所以 通过这种方法被认为是平等的两个要素是 排序集的立场,相等。排序集的行为是 定义明确,即使其排序与equals不一致;它只是 无法遵守Set接口的常规合同。
答案 1 :(得分:4)
如果您不覆盖var prop { get; set; }
方法,它会从var
类继承其行为。
当且仅当指定的对象不为null并且引用相同的实例时,此方法才返回equals
。
假设以下类:
Object
我们创建了2个实例:
true
对class VeryStupid implements Comparable
{
public int x;
@Override
public int compareTo(VeryStupid o)
{
if (o != null)
return (x - o.x);
else
return (1);
}
}
的调用返回0表示实例相等,但对VeryStupid one = new VeryStupid();
VeryStupid two = new VeryStupid();
one.x = 3;
two.x = 3;
的调用返回false表示它们不相等。
这是不一致的。
答案 2 :(得分:0)
方法int compareTo(T o)
可让您知道T o
是否(在某种程度上)优于this
,因此您可以订购T o
的列表。
在int compareTo(T o)
的场景中你必须这样做:
所以你看到你有相等的测试,两次不实现相等的最好方法就是把它放在boolean equals(Object obj)
方法中。
答案 3 :(得分:0)
compareTo
和equals
的一致性不是必需的,但强烈建议。
我会用这个例子试一试:
private static class Foo implements Comparable<Foo> {
@Override
public boolean equals(Object _other) {
System.out.println("equals");
return super.equals(_other);
}
@Override
public int compareTo(Foo _other) {
System.out.println("compareTo");
return 0;
}
}
public static void main (String[] args) {
Foo a, b;
a = new Foo();
b = new Foo();
a.compareTo(b); // prints 'compareTo', returns 0 => equal
a.equals(b); // just prints 'equals', returns false => not equal
}
当您使用默认的equals
- 方法时,您可以看到您的(可能非常重要且复杂的)比较代码被忽略。