证明equals与compareTo齐头并进

时间:2016-10-12 08:16:19

标签: java equals comparable compareto

它写在所有体面的java课程中,如果你实现Comparable接口,你应该(在大多数情况下)覆盖equals方法以匹配其行为

不幸的是,在我目前的组织中,人们试图说服我完全相反。我寻找最有说服力的代码示例向他们展示将要发生的所有邪恶。

4 个答案:

答案 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)的场景中你必须这样做:

  • 是InstanceOfThis? =>真/假;
  • 是等于这个吗? =>真/假;
  • 是SuperiorOfThis? =>真假 ;
  • 是InferiorOfThis?真假 ;

所以你看到你有相等的测试,两次不实现相等的最好方法就是把它放在boolean equals(Object obj)方法中。

答案 3 :(得分:0)

compareToequals的一致性不是必需的,但强烈建议。

我会用这个例子试一试:

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 - 方法时,您可以看到您的(可能非常重要且复杂的)比较代码被忽略。