关于JDK7的IllegalArgumentException:Comparison method violates its general contract

关于JDK7的IllegalArgumentException:Comparison method violates its general contract

今天看社区问答的时候看到的一个问题,起因是说阿里开发手册中关于Compartor的实现的问题,建议实现满足对称性,传递性和自反性.回答中提到了JDK7中如果不满足这样的性质会出现的问题.

这时我才知道原来JDK7及以上版本里,用于比较的函数一定要满足上述性质.

原因

原因是JDK7中对排序算法重新设计了,从一般的归并排序改为TimSort,这个算法需要用到满足对称性和传递性的比较函数.否则排序算法不能正常工作,会抛出IllegalArgumentException:Comparison method violates its general contract的异常.而在之前的JDK版本,仅仅只会忽略不满足性质的比较函数,没有反馈.
引用一下相关内容:

Area: API: Utilities
Synopsis: Updated sort behavior for Arrays and Collections may throw an IllegalArgumentException
Description: The sorting algorithm used by java.util.Arrays.sort and (indirectly) by java.util.Collections.sort has been replaced. The new sort implementation may throw an IllegalArgumentException if it detects a Comparable that violates the Comparable contract. The previous implementation silently ignored such a situation.
If the previous behavior is desired, you can use the new system property, java.util.Arrays.useLegacyMergeSort, to restore previous mergesort behavior.
Nature of Incompatibility: behavioral
RFE: 6804124

翻译一下Description就是,java.util.Arrays.sortjava.util.Collections.sort所使用的算法被替换了,新的算法如果发现一个可比较的对象违法了比较的约定(即三个性质),则可能抛出IllegalArgumentException,而在以前版本的实现中,对于违法比较的约定的情况,仅仅是默默地忽略了.
如果希望使用先前版本的实现,可以使用新的系统属性:java.util.Arrays.useLegacyMergeSort来恢复先前版本归并排序的行为.

如果一定要使用不满足性质的比较函数怎么办?

也是有办法的,JDK7将原来的排序算法保留了下来,当我们配置了java.util.Arrays.useLegacyMergeSorttrue后,在JDK7上也可以使用不满足性质的比较函数.
具体方法是:
1. 如果是Application,或者IDE,在要启动时加入参数-Djava.util.Arrays.useLegacyMergeSort=true
2. 如果是服务器或者其他运行环境,可以在配置文件中加入: JAVA_OPTS="$JAVA_OPTS -Djava.util.Arrays.useLegacyMergeSort=true"
3. 运行

System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");

不过据称,第3种方法不一定奏效,因为这个属性是静态的,在JVM加载了Arrays之后就不可更改了.
更加详细的描述请看文末的参考来源2与来源3

最后,最好,在实现比较函数的时候还是实现一个满足对称性,传递性和自反性的比较函数.

参考来源

最后关于TimSort的详细解释,请看参考来源1,它还提供了进一步了解TimSort的链接,可以进一步了解
关于在JDK7上配置java.util.Arrays.useLegacyMergeSort的方法,见参考来源2 ,来源3
关于JDK7的兼容性问题,请看来源4,上面引用的相关内容就是来自于此.
1. 图解JDK7的Comparison method violates its general contract异常
2. “Comparison method violates its general contract!” - TimSort and GridLayout
3. Comparison method violates its general contract! Java 7 only
4. Java SE 7 and JDK 7 Compatibility

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值