源碼
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());