为什么我的比较方法抛出异常 - 比较方法违反了它的一般合同!

时间:2011-07-08 15:07:21

标签: java android comparator contract

为什么这段代码

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()返回一个布尔值。

感谢。

7 个答案:

答案 0 :(得分: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。

答案 1 :(得分:19)

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

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

  

区域:API:实用程序

     

概要:ArraysCollections的更新排序行为可能会抛出   IllegalArgumentException

     

描述:java.util.Arrays.sort使用的排序算法   (间接)由java.util.Collections.sort替换。新的   如果检测到排序实现可能会抛出IllegalArgumentException   违反Comparable合同的Comparable。以前的   实施默默地忽略了这种情况。如果是以前的   行为是可取的,您可以使用新系统   属性java.util.Arrays.useLegacyMergeSort,用于恢复以前的属性   合并行为。

     

不相容的性质:行为

     

RFE:6804124

有关详细信息,请参阅错误数据库reference here

答案 2 :(得分:8)

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

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

答案 3 :(得分:1)

我特别赞同jon的所有回答,但是我想告诉我们应该总是在比较方法中检查null安全性,这样我们的方法永远不会中断,并且编程总是空检查是个好习惯。有关详细信息,请查看here

答案 4 :(得分:0)

也许你只有你通过Collections.sort比较的NaN值...这对我来说是一个问题,即使正确实施了compare(obj1,obj2)方法,我也得到了这个例外!检查一下!

答案 5 :(得分:0)

我今天在网络应用程序中遇到了同样的问题。在同一个阵列上工作的四个调用试图同时对它进行排序,有效地互相混淆。

答案 6 :(得分:0)

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