为什么我的比较方法违反了其总合同?

时间:2017-12-24 08:05:01

标签: java

Exception in thread "main" java.lang.IllegalArgumentException: 
Comparison method violates its general contract!
    at java.util.ComparableTimSort.mergeLo(ComparableTimSort.java:744)
    at java.util.ComparableTimSort.mergeAt(ComparableTimSort.java:481)
    at java.util.ComparableTimSort.mergeCollapse(ComparableTimSort.java:406)
    at java.util.ComparableTimSort.sort(ComparableTimSort.java:213)
    at java.util.Arrays.sort(Arrays.java:1246)
    at Solution.main(Solution.java:16)

这是我运行程序时遇到的异常。当我在类Arrays.sort的对象数组上使用Element函数时发生错误,描述为

static class Element implements Comparable<Element> {
    int pos,val;
    Element(int pos,int val){
        this.pos=pos;
        this.val=val;
    }
    public int compareTo(Element a){
        if(val!=a.val)
            return val-a.val;
        return pos-a.pos;
    }
}

在某些情况下它运行完全正常,但在其他情况下抛出上述错误。我的程序中有什么错误?为什么我的比较方法违反了一般合同?

1 个答案:

答案 0 :(得分:3)

compareTo方法中的减法可能会导致某些输入出现数字溢出,这可能会破坏总体合约。

将其更改为:

public int compareTo(Element a){
    if(val != a.val)
        return Integer.compare(val,a.val);
    return Integer.compare(pos,a.pos);
}

Comparable<T>要求compareTo定义的关系具有传递性:

  

实现者还必须确保该关系是可传递的:(x.compareTo(y)&gt; 0&amp; y.compareTo(z)&gt; 0)意味着x.compareTo(z)> 0。

现在考虑Element的三个实例具有以下val的值:

Element    val
-------    --------------------
x          11
y          Integer.MIN_VALUE+20
z          Integer.MIN_VALUE+10

现在,让我们计算一下你的方法会返回的内容:

x.compareTo(y) returns 2147483639 > 0
y.compareTo(z) returns 10 > 0

x.compareTo(z) returns -2147483647 (overflow) < 0

因此,您的方法不满足传递性。