谁能简单地解释一下,为什么这段代码抛出一个异常,“比较方法违反了它的一般契约!”,以及我该如何修复它?

private int compareParents(Foo s1, Foo s2) {
    if (s1.getParent() == s2) return -1;
    if (s2.getParent() == s1) return 1;
    return 0;
}

当前回答

违反合同通常是指比较者在比较对象时没有提供正确或一致的值。例如,你可能想要执行一个字符串比较,并强制空字符串排序到最后:

if ( one.length() == 0 ) {
    return 1;                   // empty string sorts last
}
if ( two.length() == 0 ) {
    return -1;                  // empty string sorts last                  
}
return one.compareToIgnoreCase( two );

但是这忽略了1和2都为空的情况——在这种情况下,返回了错误的值(1而不是0以显示匹配),比较器将其报告为违规。它应该写成:

if ( one.length() == 0 ) {
    if ( two.length() == 0 ) {
        return 0;               // BOth empty - so indicate
    }
    return 1;                   // empty string sorts last
}
if ( two.length() == 0 ) {
    return -1;                  // empty string sorts last                  
}
return one.compareToIgnoreCase( two );

其他回答

在我们的例子中,我们得到这个错误是因为我们不小心颠倒了s1和s2比较的顺序。所以要小心。它显然比下面的要复杂得多,但这是一个例子:

s1 == s2   
    return 0;
s2 > s1 
    return 1;
s1 < s2 
    return -1;

即使你的compareTo在理论上具有可传递性,有时细微的bug会把事情搞糟……如浮点运算错误。这件事发生在我身上。这是我的代码:

public int compareTo(tfidfContainer compareTfidf) {
    //descending order
    if (this.tfidf > compareTfidf.tfidf)
        return -1;
    else if (this.tfidf < compareTfidf.tfidf)
        return 1;
    else
        return 0;

}   

传递属性显然持有,但由于某种原因,我得到了IllegalArgumentException。事实证明,由于浮点运算中的微小错误,舍入错误导致传递属性在不应该发生的地方中断!所以我重写了代码,考虑到真正微小的差异0,它工作:

public int compareTo(tfidfContainer compareTfidf) {
    //descending order
    if ((this.tfidf - compareTfidf.tfidf) < .000000001)
        return 0;
    if (this.tfidf > compareTfidf.tfidf)
        return -1;
    else if (this.tfidf < compareTfidf.tfidf)
        return 1;
    return 0;
}   

以我为例,我做了如下事情:

if (a.someField == null) {
    return 1;
}

if (b.someField == null) {
    return -1;
}

if (a.someField.equals(b.someField)) {
    return a.someOtherField.compareTo(b.someOtherField);
}

return a.someField.compareTo(b.someField);

我忘记检查的是当a.someField和b.someField都为空时。

如果compareParents(s1, s2) == -1,则期望compareParents(s2, s1) == 1。对于你的代码,这并不总是正确的。

具体来说,如果s1. getparent () == s2 && s2. getparent () == s1。 这只是可能出现的问题之一。

我曾在一段代码中看到过这种情况,其中经常执行空值检查:

if(( A==null ) && ( B==null )
  return +1;//WRONG: two null values should return 0!!!