14

为什么这段代码

public class SponsoredComparator implements Comparator<SRE> {

    public boolean equals(SRE arg0, SRE arg1){
        return arg0.getSponsored()==arg1.getSponsored();
    }

    public int compare(SRE object1, SRE object2) {
        Log.d("SponsoredComparator","object1.getName() == "+ object1.getName());
        Log.d("SponsoredComparator","object1.getSponsored() == "+ object1.getSponsored());
        Log.d("SponsoredComparator","object2.getName() == "+ object2.getName());
        Log.d("SponsoredComparator","object2.getSponsored() == "+ object2.getSponsored());
        Log.d("SponsoredComparator","compare return == "+ (object1.getSponsored() && object2.getSponsored() ? 0 : object1.getSponsored() ? -1 : 1));
        return object1.getSponsored() && object2.getSponsored() ? 0 : object1.getSponsored() ? -1 : 1;
    }
}

抛出这个异常: ERROR/AndroidRuntime(244): java.lang.IllegalArgumentException: Comparison method violates its general contract!
ERROR/AndroidRuntime(4446): at java.util.TimSort.mergeLo(TimSort.java:743)

sre.getSponsored() 方法返回一个布尔值。

谢谢。

4

7 回答 7

27

我怀疑当没有赞助任何价值时会出现问题。无论你怎么称呼它,它都会返回 1,即

x1.compare(x2) == 1

x2.compare(x1) == 1

那是无效的。

我建议你改变这个:

object1.getSponsored() && object2.getSponsored()

object1.getSponsored() == object2.getSponsored()

在这两个地方。我实际上可能会在某处提取具有此签名的方法:

public static int compare(boolean x, boolean y)

然后这样称呼它:

public int compare(SRE object1, SRE object2) {
    return BooleanHelper.compare(object1.getSponsored(), object2.getSponsored());
}

这将使代码更清晰,IMO。

于 2011-07-08T15:09:16.790 回答
20

我假设您使用的是 JDK 7。检查以下 URL:

来自http://www.oracle.com/technetwork/java/javase/compatibility-417013.html#source

领域:API:实用程序

概要:更新了排序行为,Arrays并且Collections可能会抛出一个IllegalArgumentException

说明:java.util.Arrays.sort和(间接)使用的排序算法java.util.Collections.sort已被替换。如果新的排序实现IllegalArgumentException检测到Comparable违反Comparable合同的 a ,它可能会抛出 a 。之前的实现默默地忽略了这种情况。如果需要以前的行为,您可以使用新的系统属性java.util.Arrays.useLegacyMergeSort, 来恢复以前的合并排序行为。

不兼容的性质:行为

射频:6804124

有关更多详细信息,请参阅此处的错误数据库参考

于 2011-12-07T15:07:18.183 回答
10

equals() 和 compareTo() 之间的约定是,当 equals() 返回 true 时, compareTo() 应该返回 0,而当 equals() 为 false 时, compareTo 应该返回 -1 或 +1。

顺便说一句:我假设您的 compare() 方法不会经常调用,因为调试消息会占用大量 CPU 和内存。

于 2011-07-08T15:16:15.653 回答
1

我特别同意 jon 的所有回答,但我想告诉另外一件事,我们应该始终在 compare 方法中检查 null 安全性,以便我们的方法永远不会中断,并且在编程中始终检查 null 是一个好习惯。欲了解更多信息,请看这里

于 2014-07-24T14:59:57.400 回答
0

也许您只有通过 Collections.sort 比较的 NaN 值...这对我来说是个问题,即使正确实现了 compare(obj1, obj2) 方法,我也遇到了这个异常!检查那个!

于 2013-03-29T13:24:57.113 回答
0

我今天在 Web 应用程序中遇到了同样的问题。在同一个数组上工作的四个调用试图同时对其进行排序,从而有效地相互混淆。

于 2016-10-21T13:34:31.130 回答
0

我的解决方案:当我想对数字进行排序并且数组元素为空时,我输入 0 然后错误消失。需要注意二维数组中每一行的大小相同。

于 2018-09-15T21:07:30.280 回答