背景:项目的一个封装好工具类,在本地运行正常,但在客户的运行环境下报异常。
一、异常信息如下(原信息没保存下来,在网上搜了一段相同的异常信息):
java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.ComparableTimSort.mergeHi(ComparableTimSort.java:866)
at java.util.ComparableTimSort.mergeAt(ComparableTimSort.java:483)
at java.util.ComparableTimSort.mergeCollapse(ComparableTimSort.java:404)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:213)
at java.util.Arrays.sort(Arrays.java:1312)
at java.util.Arrays.sort(Arrays.java:1506)
at java.util.ArrayList.sort(ArrayList.java:1454)
at java.util.Collections.sort(Collections.java:141)
二、查看源代码如下:
/*
* f 字段
* x -1 升序 1降序
*
*/
public static void sortInteger(List<Map<String, Object>> list,String f,Integer x) {
Collections.sort(list,new Comparator<Map<String,Object>>() {
@Override
public int compare(Map<String, Object> o1,Map<String, Object> o2) {//o1,o2是list中的Map,可以在其内取得值,按其排序,此例为升序,s1和s2是排序字段值
String o11=o1.get(f)+"";
String o22=o2.get(f)+"";
Integer v1 = 0;
Integer v2 = 0;
if(WebUtils.isNumeric(o11)){
v1 = Integer.parseInt(o11);
}
if(WebUtils.isNumeric(o22)){
v2 = Integer.parseInt(o22);
}
if (v1 > v2) {
return -x;
} else {
return x;
}
}
});
}
当运行不报异常时,如下图:
三、原因分析,根据网上的资料,可知这里是没有考虑v1==v2的情况,当出现数据相等时,会出现异常。
另粘一段网上的原理解释:
那么比较的约束是什么呢?说明链接,大体如下:
- sgn(compare(x, y)) == -sgn(compare(y, x))
- ((compare(x, y)>0) && (compare(y, z)>0)) implies compare(x, z)>0
- compare(x, y)==0 implies that sgn(compare(x, z))==sgn(compare(y, z))
for all z
因为没有对v1==v2的判断,所以sgn(compare(x, y)) == -sgn(compare(y, x))不成立,报异常。
四、修改后的代码:
public static void sortInteger(List<Map<String, Object>> list,String f,Integer x) {
Collections.sort(list,new Comparator<Map<String,Object>>() {
@Override
public int compare(Map<String, Object> o1,Map<String, Object> o2) {//o1,o2是list中的Map,可以在其内取得值,按其排序,此例为升序,s1和s2是排序字段值
String o11=o1.get(f)+"";
String o22=o2.get(f)+"";
Integer v1 = 0;
Integer v2 = 0;
if(WebUtils.isNumeric(o11)){
v1 = Integer.parseInt(o11);
}
if(WebUtils.isNumeric(o22)){
v2 = Integer.parseInt(o22);
}
if (v1 > v2) {
return 1;
}else if (v1 < v2) {
return -1;
}else {
return 0;
}
}
});
}
修改后运行如下图,同源代码效果一致: