我认为这个问题同样适用于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。这不是一个
如果发生这种情况会带来灾难,但这是需要注意的事情。
更新:因此,恕我直言,以您当前的班级,您不能使
compareTo
与equals
保持一致。如果您真的需要这个,我看到的唯一方法是介绍一个新成员,这将给您的班级严格的自然排序。然后,如果两个对象的所有有意义的字段都比较为0,您仍然可以根据它们的特殊顺序值来确定它们的顺序。此额外成员可以是实例计数器,也可以是创建时间戳。或者,您可以尝试使用UUID。
关于c# - C#/Java:Equals测试引用身份时CompareTo的正确实现,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2439862/