案发现场
在Java开发中,我们对集合List进行排序,常会使用Collections.sort()方法进行排序,或者对于数组,使用Arrays.sort()方法进行排序。其实两者的sort()方法都是同一个,如下jdk源码:
Collections#sort
public static <T> void sort(List<T> list, Comparator<? super T> c) {
list.sort(c);
}
ArrayList#sort
@SuppressWarnings("unchecked")
public void sort(Comparator<? super E> c) {
final int expectedModCount = modCount;
// 这里,其实是调用了Arrays的sort方法
Arrays.sort((E[]) elementData, 0, size, c);
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
modCount++;
}
即最终都是调用了Arrays.sort()方法。
平时日常开发使用这个排序方法都没有问题的,但最近我开发的一个Android应用线上报了一个异常,异常栈是有Colletions.sort()引起的,异常栈信息如下:
Exception in thread "main" java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeHi(TimSort.java:899)
at java.util.TimSort.mergeAt(TimSort.java:516)
at java.util.TimSort.mergeForceCollapse(TimSort.java:457)
at java.util.TimSort.sort(TimSort.java:254)
at java.util.Arrays.sort(Arrays.java:1438)
at java.util.Arrays$ArrayList.sort(Arrays.java:3895)
at java.util.Collections.sort(Collections.java:175)
我的代码调用大概长这样:
List<FilerPackage> allPack = //省略数据赋值操作
Collections.sort(allPack, (f1, f2) -> f1.getSort() - f2.getSort());
就是这样的调动方式,平时好好的,突然某一天线上就报异常了,然后更尴尬的是,我想用线上真实数据去复现这个异常,竟然也很难复现出来,无奈,最终只能去看JDK源码,探究其真面目了。
异常分析
Collections.sort()方法注释有这么一段说明:
/ * (省略其他内容)
* @throws ClassCastException if the list contains elements that are not
* <i>mutually comparable</i> using the specified comparator.
* @throws UnsupportedOperationException if the specified list's
* list-iterator does not support the {
@code set} operation.
* @throws IllegalArgumentException (optional) if the comparator is
* found to