月眸


jdk7中Arrays.sort()和Collections.sort()排序方法使用

毛毛小妖 2019-01-23 289浏览 0条评论
首页/ 正文
分享到: / / / /

一、需求

有这样一个需求:

要求对list对象按照某个属性进行排序。于是,我在对象实体中重写了Comparable的compareTo方法。代码如下:

public int compareTo(UseStaticsVo o) {
    if (this.caseCount > o.getCaseCount()) {
	return -1;
    } else {
	return 1;
    }
}

在本地运行都很正常,但是上线的时候出现了一个很诡异的bug,异常信息如下:

Exception in thread "main"Java.lang.IllegalArgumentException: Comparison
method violates its general contract!

为此,特地百度了一下这个错误,是由于Java7内置的新排序算法导致的。突然想起来,本地使用jdk6开发的,生产环境已经升级成jdk7了。

二、结论

在Java 6中Arrays.sort()和Collections.sort()使用的是MergeSort,而在Java7中,内部实现换成了TimSort,其对对象间比较的实现要求更加严格:要满足自反性,传递性,对称性。也就是说:JDK7中的Collections.Sort方法实现中,你的返回值需要严谨全面,如果两个值是相等的,那么compare方法需要返回0,否则 可能 会在排序时抛错,而JDK6是没有这个限制的。

三、解决方案

方案1、更改内部实现:重写Comparable接口的compareTo方法的正确写法

public int compareTo(UseStaticsVo o) {
    if (this.caseCount == o.getCaseCount()) {
	return 0;
    } else if (this.caseCount > o.getCaseCount()) {
	return -1;
    } else {
	return 1;
    }
}

方案2、Java 7预留了一个接口以便于用户继续使用Java6的排序算法:在启动参数中(例如eclipse.ini)添加-Djava.util.Arrays.useLegacyMergeSort=true

方案3、将这个IllegalArgumentException手动捕获住(不推荐)

四、TimSort在Java 7中的实现

那么为什么Java7会将TimSort作为排序的默认实现,甚至在某种程度上牺牲它的兼容性(在stackoverflow上有大量的问题是关于这个新异常的)呢?我们不妨读一下这篇文章来了解一下它的思想。

最后修改:2019-01-23 18:38:05 © 著作权归作者所有
如果觉得我的文章对你有用,请随意赞赏
扫一扫支付

上一篇

发表评论

说点什么吧~

评论列表

还没有人评论哦~赶快抢占沙发吧~