为什么Comparator <integer []>抛出异常?

时间:2016-02-01 21:55:13

标签: java comparator

我有一个例外

java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeHi(TimSort.java:868)
at java.util.TimSort.mergeAt(TimSort.java:485)
at java.util.TimSort.mergeCollapse(TimSort.java:408)
at java.util.TimSort.sort(TimSort.java:214)
at java.util.TimSort.sort(TimSort.java:173)
at java.util.Arrays.sort(Arrays.java:659)
at Main.main(Main.java:64)

使用此代码时:

Arrays.sort(arr, new Comparator<Integer[]>(){  //arr is 2D array
        public int compare(Integer[] o1, Integer[] o2){
            return o1[2]==o2[2]?0:o1[2]>o2[2]?1:-1;
        }
    });

我认为这与不满足比较的传递性有关,但当我做了一点这样的改变时:

Arrays.sort(arr, new Comparator<Integer[]>(){  //arr is 2D array
        public int compare(Integer[] o1, Integer[] o2){
            return o1[2].compareTo(o2[2]); // here is the change
        }
    });

不再生成异常。 我无法理解这个问题的解释,因为我确信除了compareTo()方法之外,还可以使用关系运算符(&gt;,&lt;,=)来比较Integer实例

Integer x = 1;
Integer y = 2;
System.out.println(x<y);

按预期打印true

任何机构都可以澄清吗?

3 个答案:

答案 0 :(得分:7)

问题在于:

o1[2]==o2[2]

这是比较Integer s的身份。平等实例不一定相同。例如:

Integer a = new Integer(128);
Integer b = new Integer(128);
System.out.println(a == b);      // False, instances are not identical.
System.out.println(a.equals(b)); // True, instances are equal.

应该是:

o1[2].equals(o2[2])

或者,处理o1[2] null

Objects.equal(o1[2], o2[2])

答案 1 :(得分:1)

因为你使用的是Integer而不是int,所以这是无效的:

o1[2]==o2[2]?0:o1[2]>o2[2]?1:-1;

您需要使用equalscompareTo,而不是==

答案 2 :(得分:0)

您要排序的数组由Integer 对象组成。这些不仅仅是普通的旧整数。

一个普通的旧整数只是一个坐在内存中的数字。

Integer对象是一个类的实例,它填充与基本整数相同的角色,但也有一堆与之关联的方法和数据。这是作为一个数据或作为一个对象之间的区别。

==运算符比较内存中的数字。对于对象的实例,它将比较内存中的位置,而不是您想要的数字值。

对于Integer(和其他类似数字)对象,您必须使用compareTo()方法。

您的解决方案是按建议使用compareTo()方法,或将数组更改为普通旧整数。

您也可以将其保留为Integer对象,然后使用Integer.intValue()获取返回的普通旧整数,然后您可以使用==比较。但这很复杂,IMO。