-Djava.util.Arrays.useLegacyMerg
2020-12-20 本文已影响0人
zh_harry
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 版本以上,Comparator 要满足自反性,传递性,对称性,不然 Arrays.sort,
Collections.sort 会报 IllegalArgumentException 异常。
说明:
1) 自反性:x,y 的比较结果和 y,x 的比较结果相反。
2) 传递性:x>y,y>z,则 x>z。
3) 对称性:x=y,则 x,z 比较结果和 y,z 比较结果相同。
重现
package com.sparrow.jdk.collections;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
/**
* -Djava.util.Arrays.useLegacyMergeSort=true
*/
public class DictionaryTest {
public static void main(String[] args) {
//exception
int[] array = new int[]{1, 2, 3, 2, 2, 3, 2, 3, 2, 2, 3, 2, 3, 3, 2, 2, 2, 2, 2, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
array = new int[]{2, 3, 2, 2, 3, 2, 3, 2, 2, 3, 2, 3, 3, 2, 2, 2, 2, 2, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
List<DictionaryEntry> list = new ArrayList<>();
Set<DictionaryEntry> set = new TreeSet<>();
for (int i = 0; i < array.length; i++) {
DictionaryEntry entry = new DictionaryEntry();
entry.setItemId(i);
entry.setScore(new BigDecimal(array[i]));
list.add(entry);
set.add(entry);
}
long current = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
//System.out.println(set.size());
Collections.sort(list);
//System.out.println(list.size());
}
System.out.println(System.currentTimeMillis() - current);
}
public static class DictionaryEntry implements Comparable<DictionaryEntry> {
public DictionaryEntry() {
}
private Integer itemId;
private BigDecimal score;
public BigDecimal getScore() {
return score;
}
public void setScore(BigDecimal score) {
if (score != null) {
this.score = score.setScale(5, RoundingMode.HALF_UP);
} else {
this.score = new BigDecimal(0);
}
}
public Integer getItemId() {
return itemId;
}
public void setItemId(Integer itemId) {
this.itemId = itemId;
}
@Override
public int compareTo(DictionaryEntry o) {
//tree set o.score.compareTo(this.score)==0时去重
//手动设置非0时,throw new IllegalArgumentException("Comparison method violates its general contract!");
//-Djava.util.Arrays.useLegacyMergeSort=true 解决兼容
return o.score.compareTo(this.score) == 0 ? -1 : o.score.compareTo(this.score);
}
}
}