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.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 java.util.Collections.sort(Collections.java:217)
有人可以解释为什么我的比较器有时会抛出上述异常。
注意:myObject中的id字段是long类型。
Collections.sort(objectList, new Comparator<MyObject>() {
@Override
public int compare(final myObject myobject1, final MyObject myObject2) {
return (int)(myObject1.getId() - myObject2.getId());
}
});
解决方案:
基于@amit的答案
return (int)(Long.compare(myObject1.getId(), myObject2.getId());
答案 0 :(得分:4)
如果ID的绝对值为相对较高的整数,则可能会遇到整数溢出,这会导致echo "# some change" >> Gemfile && git commit -m 'some change' Gemfile
为负数。这显然是错误的,并打破了比较国的合同。
使用Integer.compare()
(或类似Long.compare()
,Double.compare()
...)而不是减去数字以避免它。
修改强>
具体来说,这里的问题仍然是整数溢出,当它输出一个long值时,其32个LSb在[{1}}到VERY_HIGH_INT - VERY_LOW_INT
范围内[2 ^ 31,2 ^ 32],这会导致它错误的否定。 Demo in ideone
解决方案是一样的。使用long
答案 1 :(得分:0)
Java 7
已将MergeSort
方法中的默认排序算法从TimSort
更改为java.util.Arrays.sort
。
java.util.Arrays.sort
和(indirectly
)java.util.Collections.sort
使用的排序算法已被替换。如果新排序实现检测到违反Comparable合同的Comparable,则可能会抛出IllegalArgumentException
。
为了向后兼容并从Java版本6恢复行为,请添加新的系统属性 - java.util.Arrays.useLegacyMergeSort。
有关详细信息,请参阅以下链接 -
http://www.oracle.com/technetwork/java/javase/compatibility-417013.html#source