我正在将一个项目从 JDK 7 升级到 JDK 8,最初我们遇到了一个异常:
java.lang.IllegalArgumentException: Comparison method violates its general contract! at java.util.TimSort.mergeHi(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)
我们通过使用java.util.Arrays.useLegacyMergeSort的系统属性作为true来解决这个问题。之后异常得到解决,但它执行的排序是错误的(排序不正确)。
注意:在 JDK 7 中,相同的代码可以完美运行(没有此系统属性)
public class SortTableModelRowComparator implements Comparator<TableModelSortingRow>
{
private boolean ascending = true;
protected int[] sortingColumns;
/**
* Constructor
*
*/
public SortTableModelRowComparator(boolean pSortAscendending, int[] pSortingColumns)
{
ascending=pSortAscendending;
sortingColumns=pSortingColumns;
}
@Override
public int compare(TableModelSortingRow o1,
TableModelSortingRow o2) {
BigDecimal firstvalue=(BigDecimal)o1.getValue(7);
BigDecimal secondvalue=(BigDecimal)o2.getValue(7);
return firstvalue.compareTo(secondvalue);
}
}
最佳答案
这就是使用该标志的问题。
原来的异常是指你的Comparator
有问题或Comparable
的比较运算。它的某些内容违反了 Comparable
有效比较需要遵守的契约1。本质上,这是您的应用程序中的一个错误。
当您设置该标志时,您就是在告诉 JVM 忽略该问题。在某些情况下,您可以逃脱惩罚。在其他情况下......比如你的......后果将是不正确的。
解决方案:找出出现异常的原因,并解决该问题。
请注意,这可能是比较本身的问题,也可能是在对对象进行排序时发生了某些变化,这就是导致违反契约(Contract)的原因。
<小时/>Note: In JDK 7 same code work perfectly(without this System properties)
Java 7 和 Java 8 中使用的排序算法不同2。但是,您很可能在 Java 7 中得到了不正确的排序,而您却没有注意到。
<小时/>1 - Comparator
contract如下:
“在前面的描述中,符号sgn(expression)
表示数学符号函数,它被定义为根据表达式的值是负数、零还是正数返回-1、0或1之一.
实现者必须确保
sgn(compare(x, y)) == -sgn(compare(y, x))
对于所有人x
和y
。 (这意味着compare(x, y)
必须抛出异常当且仅当compare(y, x)
抛出异常。)实现者还必须确保关系是可传递的:
((compare(x, y)>0) && (compare(y, z)>0))
意味着compare(x, z)>0
.最后,实现者必须确保
compare(x, y)==0
意味着sgn(compare(x, z))==sgn(compare(y, z))
对于所有人z
”
2 - 此外,在 Java 7 中,算法的实现不会检查比较操作中的不正确行为。这解释了为什么在 Java 7 中没有异常(exception)。
关于java - 将 useLegacyMergesort 实现为 true 后,Collection.sort 在 JDK 8 中无法正确排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37805639/