jdk7中Arrays.sort()和Collections.sort()排序方法使用
网站首页 文章专栏 jdk7中Arrays.sort()和Collections.sort()排序方法使用
jdk7中Arrays.sort()和Collections.sort()排序方法使用
编辑时间:2019-05-06 18:11 作者:毛毛小妖 浏览量:155 评论数: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上有大量的问题是关于这个新异常的)呢?我们不妨读一下这篇文章来了解一下它的思想。

推荐文章
来说两句吧
最新评论
    还没有人评论哦,快来坐沙发吧!