Java7-比较方法违反了其一般约定(TimSort.java)

Ast*_*tro 0 java sorting java-7

这是我得到的堆栈跟踪

Caused by: java.lang.IllegalArgumentException: Comparison method violates its general contract!
        at java.util.TimSort.mergeLo(TimSort.java:777)
        at java.util.TimSort.mergeAt(TimSort.java:514)
        at java.util.TimSort.mergeCollapse(TimSort.java:441)
        at java.util.TimSort.sort(TimSort.java:245)
        at java.util.Arrays.sort(Arrays.java:1512)
        at java.util.ArrayList.sort(ArrayList.java:1454)
        at java.util.Collections.sort(Collections.java:175)
        at xxx.sortDisplayFields(OfferFieldLayout.java:521)
Run Code Online (Sandbox Code Playgroud)

这是比较方法:

  public int compare(Field pObject1, Field pObject2)
{
    int compare = 0;              

   //...
    if (compare == 0)
    {
        if (pObject1.hashCode() <= pObject2.hashCode())
        {
            compare = -1;
        }
        else
        {
            compare =  1;
        }
    }

    return compare;
}
Run Code Online (Sandbox Code Playgroud)

我认为这是由于不尊重传递性而导致的:传递性:如果A> B和B> C,那么对于任何A,B和C:A>C。我试图提出一个反例,但我失败了在这里,任何帮助表示赞赏!

mar*_*ran 5

您的函数永远不会返回0!这意味着,如果对象中的所有内容(包括哈希码)相等,pObject1.compare(pObject2)则将不相等pObject2.compare(pObject1)。比较函数必须对称。我还以为你换周围-1,并1在该测试中,所以你最后的检查应该是这样的:

if (compare == 0) {
    if (pObject1.hashCode() < pObject2.hashCode()) {
        compare = 1;
    } else if (pObject1.hashCode() > pObject2.hashCode()) {
        compare =  -1;
    }
}

return compare;
Run Code Online (Sandbox Code Playgroud)

顺便说一句,您的对象应该实现Comparable接口,并且应该调用方法compareTo

最后,比较哈希码并不是一个好主意。即使对象不相等,它们也可能发生碰撞。这意味着当对象不相等时,您的compareTo方法可以返回0。这也违反了compareTo合同。