源码
listRs = list.stream().sorted((n1, n2) -> {
BigDecimal value1 = n1.getValue1();
BigDecimal value2 = n2.getValue1();
if (value1.subtract(value2).intValue() > 0) {
return -1;
}
if (value1.subtract(value2).intValue() < 0) {
return 1;
}
return 0;
}).collect(Collectors.toList());
异常
java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeHi(TimSort.java:868)
at java.util.TimSort.mergeAt(TimSort.java:485)
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)
...
原因
JDK7中的Collections.Sort方法实现中,如果两个值是相等的,那么compare方法需要返回0,否则 可能 会在排序时抛错,而JDK6是没有这个限制的。
这里网上现有的解决方案有:
3. 解决方法
解决该问题至少有3种方法。
(1)使用JDK1.6版本运行
(2)修改The ONE源码,使其满足传递性
只需要更改Router的比较器Comparator就可以了,比如MaxProp的MaxPropComparator:
private class MaxPropComparator implements Comparator {
…
}
(3)重新编译源码
加上一些选项,重新编译The ONE源码,使其能在JDK1.6+能正常运行[1]。
方法一:在main函数第一行加入如下代码:
System.setProperty(“java.util.Arrays.useLegacyMergeSort”, “true”);
方法2:编译时,加上选项-Djava.util.Arrays.useLegacyMergeSort=true,完整Java编译如下:
java -Djava.util.Arrays.useLegacyMergeSort=true -d64 -Xms512m -Xmx4g -cp .:lib/ECLA.jar:lib/DTNConsoleConnection.jar core.DTNSim $*
我的解决办法:
1、网上也有提到,如果重写了compare方法,需要判断大于,小于,等于;
2、用java的compareTo()方法,让jdk去处理;
修改后
listRs = list.stream().sorted((n1, n2) -> {
BigDecimal value1 = n1.getValue1();
BigDecimal value2 = n2.getValue1();
//倒序,所以乘 -1
return -1 * value1.compareTo(value2);
}).collect(Collectors.toList());