可比接口取决于大小?

Jok*_*ker 4 java comparable

我正在研究Comparable界面,发现IllegalArgumentException当我放入size=50下面的程序时它正在抛出,并且当我放入时工作正常size =5.

    public class Test {
    public static void main(String[] args) {
        int size = 50;
        Test compareTest = new Test();
        compareTest.test(size);
    }

    public void test(int size) {
        List<TestObject> requests = new ArrayList<TestObject>();
        for (int index = 0; index < size; index++) {
            TestObject request = new TestObject();
            request.value = index;
            requests.add(request);
        }
        Collections.sort(requests);
    }

}

class TestObject implements Comparable<TestObject> {
    public int value;

    public int compareTo(TestObject req) {
        if (value % 3 == 0) {
            return -1;
        } else if (value % 3 == 1) {
            return 0;
        }

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

我不确定这个问题的根本原因,有人可以帮我解决这个问题.

下面给出了异常堆栈跟踪.

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)
Run Code Online (Sandbox Code Playgroud)

dav*_*xxx 6

您违反了可比较合同.

实际上你不比较它们之间的两个对象,但是你只根据3的模数结果比较value当前TestObject对象的字段.你不使用TestObjectcompareTo()方法中作为参数传递的对象.

假设您有List两个TestObject带有3as value字段的对象

这两个对象将返回-1:

    if (value % 3 == 0) {
        return -1;
    } 
Run Code Online (Sandbox Code Playgroud)

但根据规则:

实现者必须确保所有x和y的sgn(x.compareTo(y))== -sgn(y.compareTo(x)).(这意味着如果y.compareTo(x)抛出异常,x.compareTo(y)必须抛出异常.)

假设第一个对象是x,第二个对象是y.
如果y.compareTo(x)返回负数(例如-1),x.compareTo(y)则应返回正数(例如1).

我正在使用Comparable接口,发现当我在下面的程序中放置size = 50时它会抛出IllegalArgumentException并且当我把size = 5时工作正常

事实上,当你违反Comparable合同时,结果是不可预测的.它可能适用于某些特定值,不适用于其他特定值.
它可能在特定的JVM版本中工作,而在另一个版本中不起作用.
试图理解它失败的原因或者它对特定值的成功可能很有意思,但实际上没有用.
试图理解合同以尊重合同要好得多.因为今天它的工作正在进行中,但明天在未来的实施中,它可能会改变.只有API才是保证.

  • @ShowStopper因为你很幸运.在所有情况下,Timsort都不会尝试验证您的比较方法是否遵守合同.它只有在有理由时才会注意到它.大多数排序算法甚至不检查; 他们表现得很糟糕.在任何情况下,除了没有抛出异常外,我不知道"工作正常"是什么意思; 你的`compareTo`没有定义订单,因为它没有比较两个对象,所以我不知道你期望排序数组看起来是什么顺序. (3认同)