jdk6+(不含6) 比较规则遵循规则:对称,反身,传递!

java.lang.IllegalArgumentException: Comparison method violates its general contract!
[2017-05-18T11:22:20.626][DBG]io exception
at java.util.ComparableTimSort.mergeHi(Unknown Source)
at java.util.ComparableTimSort.mergeAt(Unknown Source)
at java.util.ComparableTimSort.mergeForceCollapse(Unknown Source)
at java.util.ComparableTimSort.sort(Unknown Source)
at java.util.Arrays.sort(Unknown Source)
at com.vixtel.insight.xrobot.test.MP4Parser.showSizeToTimeStamp(TestScriptFlv.java:1400)
at com.vixtel.insight.xrobot.test.MP4Parser.handleMoov(TestScriptFlv.java:1182)
at com.vixtel.insight.xrobot.test.MP4Parser.parseVersion2nd(TestScriptFlv.java:1111)
at com.vixtel.insight.xrobot.test.TestScriptFlv.onReceive(TestScriptFlv.java:627)
at com.vixtel.insight.xrobot.test.TestScriptFlv$1.run(TestScriptFlv.java:457)
at java.lang.Thread.run(Unknown Source)


jdk 7的sort函数的实现变了,造成了这个问题。改一下系统设置,还是选择使用老版本的排序方法,在代码前面加上这么一句话:System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 问题原因(百度知):产生该问题的原因是JDK1.6+要求所有比较器必须是可传递的(transitive),比如有A > B 和B > C,必须得保证有推出A > C(同理,对于=和<也需满足传递性)。而The ONE源码是基于JDK1.6的,JDK1.6没有该要求。

 发散思维:(我的类BeginToEnd的确没有传递性 >> 对称性、传递性、反身性 >> 完备性)

public int compareTo(BeginToEnd o) {
if (this.beginSize == o.beginSize && this.endSize == o.endSize) {
return 0;
}else if (this.beginSize > o.beginSize) {
return 1;
} else {
return -1;
}
[1,2].compareTo([1,3]) = -1  => [1,2] < [1,3]
[1,3].compareTo([1,2]) = -1  => [1,3] < [1,2]
显然有问题,自相矛盾!!!


修改为:


public int compareTo(BeginToEnd o) {
if (this.beginSize > o.beginSize) {
return 1;
}else if(this.beginSize < o.beginSize) {
return -1;
}else{
                if(this.endSize == o.endSize){
                    return 0;
                }
                else if(this.endSize > o.endSize) {
                    return -1;
                }else {
                    return 1;
                }
            }




其他摘录:

根据他们的提示,我大概了解了compare方法需要返回 1,-1, 0即你的返回值要符合约定。
于是我又按照异常提示看了Collections的sort方法源码,如图:.......

继续跟踪Arrays类的sort方法:

看到这里我基本就豁然开朗了,因为抛异常的地方是在TimSort类里,说明实际走的是else分支,所以有了第一种解决方法,添加-Djava.util.Arrays.useLegacyMergeSort=true这个JVM参数,其实要真正解决这个问题,要符合规范的实现compare方法,因为他写的代码里没有考虑对象o1和对象o2为 Null的情况,即当o1与o2都为null时两者大小如何判定呢,当o1为null但o2不为null时两者大小又如何判定了呢,同理当o2为null

但o1不为null时两者大小又如何判定呢又不得而知,或许你又会说,我这两个对象不可能为null,但那是你认为,JVM不知道,它只要求你的逻辑必须严谨,严格考虑各种情况下两者大小的判定原则。

(我的理解:对于comparable,可以不用考虑null,因为comparable在类中实现,必须有this不为null才会成功调用,所以需要保证不为null即可;对于comparator可以考虑作者的做法)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值