Collectons.sort的坑
[Request processing failed; nested exception is java.lang.IllegalArgumentException: Comparison method violates its general contract!] with root cause java.lang.IllegalArgumentException: Comparison method violates its general contract! at java.util.TimSort.mergeLo(Unknown Source) at java.util.TimSort.mergeAt(Unknown Source) at java.util.TimSort.mergeCollapse(Unknown Source) at java.util.TimSort.sort(Unknown Source) at java.util.Arrays.sort(Unknown Source) at java.util.ArrayList.sort(Unknown Source) at java.util.Collections.sort(Unknown Source)
以上是报错。
具体代码如下:
Collections.sort(data, new Comparator<Map<String, Object>>() { @Override public int compare(Map<String, Object> o1, Map<String, Object> o2) { String o1Bbm1 = CourtUtils.trim(o1.get("CBBM1")); String o2Bbm1 = CourtUtils.trim(o2.get("CBBM1")); TDepart tDepart1 = CacheUtils.getTDepart(o1Bbm1); TDepart tDepart2 = CacheUtils.getTDepart(o2Bbm1); if ("".equals(o1Bbm1) || tDepart1 == null) { return 1; } if ("".equals(o2Bbm1) || tDepart2 == null) { return -1; } Integer pxh0 = tDepart1.getPxh() == null ? 0 : tDepart1.getPxh(); Integer pxh1 = tDepart2.getPxh() == null ? 0 : tDepart2.getPxh(); if (pxh0 == pxh1) { return o1Bbm1.compareTo(o2Bbm1); } else { return pxh0 - pxh1; } } });
在对list进行排序时,报错。但是正是环境上是没问题的。所以要排查兼容测试环境的问题,防止正式环境报错。
首先要知道,在 JDK7 版本以上,Comparator 要满足自反性,传递性,对称性,不然 Arrays.sort,Collections.sort 会报 IllegalArgumentException 异常。
自反性:当 两个相同的元素相比时,compare必须返回0,也就是compare(o1, o1) = 0;
反对称性:如果compare(o1,o2) = 1,则compare(o2, o1)必须返回符号相反的值也就是 -1;
传递性:如果 a>b, b>c, 则 a必然大于c。也就是compare(a,b)>0, compare(b,c)>0, 则compare(a,c)>0。
最容易出问题的,就是传递性。比如:
假设存在三个元素:stu1, null,stu2,则
compare(stu1, null)= 0,
compare(null, stu2) = 0,
compare(stu1,stu2) =1 很明显违反了传递性原则。
那么,咋改呢?
多进行一次判断,就可以。
Collections.sort(data, new Comparator<Map<String, Object>>() { @Override public int compare(Map<String, Object> o1, Map<String, Object> o2) { String o1Bbm1 = CourtUtils.trim(o1.get("CBBM1")); String o2Bbm1 = CourtUtils.trim(o2.get("CBBM1")); TDepart tDepart1 = CacheUtils.getTDepart(o1Bbm1); TDepart tDepart2 = CacheUtils.getTDepart(o2Bbm1); if ("".equals(o1Bbm1) || tDepart1 == null) { if ("".equals(o2Bbm1) || tDepart2 == null) { return 0; } return 1; } if ("".equals(o2Bbm1) || tDepart2 == null) { return -1; } Integer pxh0 = tDepart1.getPxh() == null ? 0 : tDepart1.getPxh(); Integer pxh1 = tDepart2.getPxh() == null ? 0 : tDepart2.getPxh(); if (pxh0 == pxh1) { return o1Bbm1.compareTo(o2Bbm1); } else { return pxh0 - pxh1; } } });
完活。
我不是来改变世界的