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

los*_*aby 14 java android contract comparator

为什么这个代码

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

抛出此异常: 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()返回一个布尔值.

谢谢.

Jon*_*eet 27

我怀疑当这两个价值都没有得到赞助时就会出现问题.无论你怎么称呼,它都将返回1,即

x1.compare(x2) == 1

x2.compare(x1) == 1
Run Code Online (Sandbox Code Playgroud)

那是无效的.

我建议你改变这个:

object1.getSponsored() && object2.getSponsored()
Run Code Online (Sandbox Code Playgroud)

object1.getSponsored() == object2.getSponsored()
Run Code Online (Sandbox Code Playgroud)

在这两个地方.我可能会某个地方用这个签名提取出一个方法:

public static int compare(boolean x, boolean y)
Run Code Online (Sandbox Code Playgroud)

然后像这样调用它:

public int compare(SRE object1, SRE object2) {
    return BooleanHelper.compare(object1.getSponsored(), object2.getSponsored());
}
Run Code Online (Sandbox Code Playgroud)

这将使代码更清晰,IMO.


nar*_*esh 19

我假设您使用的是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合同的情况,新的排序实现可能会抛出.以前的实现默默地忽略了这种情况.如果需要先前的行为,则可以使用新的系统属性java.util.Arrays.useLegacyMergeSort来恢复先前的mergesort行为.

不相容的性质:行为

RFE:6804124

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

  • 你几乎是对的.OP使用Android(而不是JDK 7),但你的引用仍然是正确的,因为JDK 7和Android都使用`TimSort`算法,如果与`Comparable`一起使用违反`Comparable`合同,它会抛出`IllegalArgumentException`. (5认同)

Pet*_*rey 8

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

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

  • 那些调试消息只是帮助修复这个bug. (3认同)