1. 程式人生 > >IllegalArgumentException: Comparison method violates its general contract錯誤詳細內容

IllegalArgumentException: Comparison method violates its general contract錯誤詳細內容

 今天在開發的過程中出現了一個比較詭異的報錯。
擷取部分報錯資訊
java.lang.IllegalArgumentException: Comparison method violates its general contract!
	at java.util.TimSort.mergeLo(TimSort.java:747) ~[na:1.7.0_65]
	at java.util.TimSort.mergeAt(TimSort.java:483) ~[na:1.7.0_65]
	at java.util.TimSort.mergeCollapse(TimSort.java:410) ~[na:1.7.0_65]
	at java.util.TimSort.sort(TimSort.java:214) ~[na:1.7.0_65]
	at java.util.TimSort.sort(TimSort.java:173) ~[na:1.7.0_65]
	at java.util.Arrays.sort(Arrays.java:659) ~[na:1.7.0_65]
	at java.util.Collections.sort(Collections.java:217) ~[na:1.7.0_65]

度娘之後.原來是 jdk1.7中修改了 Array.sort的演算法.不在使用之前MergeSort ,而是使用新的TimeSort,其物件間的要求更加嚴格
a). sgn(compare(x, y)) == -sgn(compare(y, x)) 
b). (compare(x, y)>0) && (compare(y, z)>0) 意味著 compare(x, z)>0 
c). compare(x, y)==0 意味著對於任意的z:sgn(compare(x, z))==sgn(compare(y, z)) 均成立
詳情閱讀.Comparator<T>.compare 方法說明

解決以上錯誤的方法
1.更改內部實現:例如對於上個例子,就需要更改為
public int compare(ComparatorTest o1, ComparatorTest o2) { 
    return o1.getValue() == o2.getValue() ? 0 :  
                (o1.getValue() > o2.getValue() ? 1 : -1); 
}


2.Java 7預留了一個介面以便於使用者繼續使用Java 6的排序演算法:在啟動引數中(例如eclipse.ini)新增-Djava.util.Arrays.useLegacyMergeSort=true
3.將這個IllegalArgumentException手動捕獲住(不推薦)