有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

排序Java7比较方法违反了它的一般约定(TimSort.java)

这是我得到的堆栈跟踪

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)

以下是比较方法:

  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;
}

我认为这是因为传递属性没有得到尊重: 及物性:如果A>;B和B>;C然后对于任何A、B和C:A>;C 我试图想出一个反例,但我在这里失败了,任何帮助感谢


共 (2) 个答案

  1. # 1 楼答案

    你的函数永远不能返回0!这意味着,如果对象中的所有内容都相等,包括hashcode,那么pObject1.compare(pObject2)将不等于pObject2.compare(pObject1)。比较函数必须是对称的。我还认为您在该测试中交换了-11,因此您最后的检查应该是:

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

    顺便说一下,您的对象应该实现Comparable接口,并且该方法应该被称为compareTo

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

  2. # 2 楼答案

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

    这一部分肯定与compareTo契约不兼容,因为如果散列码相等,那么比较就不相等。相反,您应该使用return Integer.compare(pObject1.hashCode(), pObject2.hashCode()),假设您想要使用哈希代码进行比较。(这通常不是一个好主意,因为哈希代码可能会发生冲突。)