我认为这个问题同样适用于C#和Java,因为两者都要求{c,C} ompareTo与{e,E}保持一致:

假设我希望equals()方法与引用检查相同,即:

public bool equals(Object o) {
    return this == o;
}


在那种情况下,如何实现compareTo(Object o)(或它的一般等效项)?一部分很容易,但是我不确定另一部分:

public int compareTo(Object o) {
    MyClass other = (MyClass)o;
    if (this == other) {
        return 0;
    } else {
        int c = foo.CompareTo(other.foo)
        if (c == 0) {
            // what here?
        } else {
            return c;
        }
    }
}


我不能盲目地返回1或-1,因为解决方案应符合compareTo的正常要求。我可以检查所有实例字段,但是如果它们全部相等,我仍然希望compareTo返回一个非0的值。a.compareTo(b)==-(b.compareTo(a) ),并且只要对象的状态不变,顺序就应保持一致。

但是,我不在乎跨虚拟机调用的顺序。这使我认为,如果可以的话,我可以使用诸如内存地址之类的东西。再说一次,也许那行不通,因为垃圾收集器可以决定移动我的对象。

hashCode是另一种想法,但我希望它始终是唯一的,而不仅仅是大部分。

有任何想法吗?

最佳答案

首先,如果您使用的是Java 5或更高版本,则应实现Comparable<MyClass>而不是普通的Comparable,因此,您的compareTo方法应采用类型为MyClass而不是Object的参数:

public int compareTo(MyClass other) {
    if (this == other) {
        return 0;
    } else {
        int c = foo.CompareTo(other.foo)
        if (c == 0) {
            // what here?
        } else {
            return c;
        }
    }
}


关于您的问题,Effective Java中的Josh Bloch(第3章,项目12)说:


  实现者必须确保sgn(x.compareTo(y))== -sgn(y.compare-
  全部x和y为((x))。 (这意味着x.compareTo(y)必须抛出异常
  当且仅当y.compareTo(x)引发异常。)


这意味着如果以上代码中的c == 0,则必须返回0。

这又意味着您可以拥有不相等的对象A和B,但是它们的比较返回0。布洛赫先生对此有何评论?


  强烈建议(但并非严格要求)(x.compareTo(y)
  == 0)==(x.equals(y))。一般来说,任何实现
  可比接口并违反此条件应明确指出
  这个事实。推荐的语言是“注意:该课程自然
  与等式不一致的顺序。”





  一个类,其compareTo方法施加一个顺序
  与equals不一致的仍然可以使用,但是包含
  该类别的元素可能不遵守适当馆藏的一般合同
  接口(集合,集合或映射)。这是因为一般合同
  这些接口是根据equals方法定义的,但已排序的集合
  使用compareTo施加的相等性测试代替equals。这不是一个
  如果发生这种情况会带来灾难,但这是需要注意的事情。


更新:因此,恕我直言,以您当前的班级,您不能使compareToequals保持一致。如果您真的需要这个,我看到的唯一方法是介绍一个新成员,这将给您的班级严格的自然排序。然后,如果两个对象的所有有意义的字段都比较为0,您仍然可以根据它们的特殊顺序值来确定它们的顺序。

此额外成员可以是实例计数器,也可以是创建时间戳。或者,您可以尝试使用UUID

关于c# - C#/Java:Equals测试引用身份时CompareTo的正确实现,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2439862/

10-12 19:30