2

下面是导致异常的代码块,

代码 :

            Collections.sort( arrayList, new Comparator()
            {
                public int compare( Object o1, Object o2 )
                {
                TypeAdapterSort tas1 = ( TypeAdapterSort ) o1;
                TypeAdapterSort tas2 = ( TypeAdapterSort ) o2;
                if ( tas1.order < tas2.order )
                    return -1;
                else
                    return 1;
                }
            } );

例外 :

java.lang.IllegalArgumentException: Comparison method violates its general contract!
                    at java.util.TimSort.mergeLo(TimSort.java:747)
                    at java.util.TimSort.mergeAt(TimSort.java:483)
                    at java.util.TimSort.mergeForceCollapse(TimSort.java:426)
                    at java.util.TimSort.sort(TimSort.java:223)
                    at java.util.TimSort.sort(TimSort.java:173)
                    at java.util.Arrays.sort(Arrays.java:659)
                    at java.util.Collections.sort(Collections.java:217)

当我运行与独立程序相同的代码时,问题永远不会发生。这里的比较器有什么问题?有没有办法在独立代码中重现问题?

此问题仅在 Java 1.7 上出现,因为 Arrays.sort 和 Collections.sort 的实现发生了变化。如何更改上述代码以避免该问题?另外,如何在独立代码中重现此问题?

4

2 回答 2

4

比较器遵守一般合同。看这个:

if ( tas1.order < tas2.order )
    return -1;
else
    return 1;
}

现在考虑两个具有相同 的对象order。比较它们应该返回 0。

Integer.compare如果您使用的是 Java 7 ,最好只委托给:

return Integer.compare(tas1.order, tas2.order);

或者,如果您使用的是早期版本:

return tas1.order == tas2.order ? 0
     : tas1.order < tas2.order ? -1
     : 1;
于 2013-04-18T06:19:09.910 回答
1

您不需要只返回 -1 或 1。一般合同规定,如果第一个元素更小,则返回的数字必须为负数,如果它们相等则返回零,如果第二个元素更小,则返回正数。所以你可以跳过 if/else 语句,直接返回:

return tas1.order - tas2.order;
于 2013-04-18T06:21:31.617 回答