简体   繁体   English

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

[英]why does my compare method throw exception — Comparison method violates its general contract!

Why does this code 为什么这个代码

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;
    }
}

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

The method sre.getSponsored() returns a boolean. 方法sre.getSponsored()返回一个布尔值。

Thanks. 谢谢。

I suspect the problem occurs when neither value is sponsored. 我怀疑当这两个价值都没有得到赞助时就会出现问题。 That will return 1 whichever way you call it, ie 无论你怎么称呼,它都将返回1,即

x1.compare(x2) == 1

x2.compare(x1) == 1

That's invalid. 那是无效的。

I suggest you change this: 我建议你改变这个:

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

to

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

in both places. 在这两个地方。 I would probably actually extract this out a method with this signature somewhere: 我可能会某个地方用这个签名提取出一个方法:

public static int compare(boolean x, boolean y)

and then call it like this: 然后像这样调用它:

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

That will make the code clearer, IMO. 这将使代码更清晰,IMO。

I assume that you are using JDK 7. Check the following URL: 我假设您使用的是JDK 7.请检查以下URL:

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

Area: API: Utilities 区域:API:实用工具

Synopsis: Updated sort behavior for Arrays and Collections may throw an IllegalArgumentException 概要: ArraysCollections更新排序行为可能会抛出IllegalArgumentException

Description: The sorting algorithm used by java.util.Arrays.sort and (indirectly) by java.util.Collections.sort has been replaced. 描述: java.util.Arrays.sort和(间接) java.util.Collections.sort使用的排序算法已被替换。 The new sort implementation may throw an IllegalArgumentException if it detects a Comparable that violates the Comparable contract. 如果新的排序实现检测到违反Comparable合同的Comparable ,则可能抛出IllegalArgumentException The previous implementation silently ignored such a situation. 以前的实现默默地忽略了这种情况。 If the previous behavior is desired, you can use the new system property, java.util.Arrays.useLegacyMergeSort , to restore previous mergesort behavior. 如果需要先前的行为,则可以使用新的系统属性java.util.Arrays.useLegacyMergeSort来恢复先前的mergesort行为。

Nature of Incompatibility: behavioral 不相容的性质:行为

RFE: 6804124 RFE:6804124

For more detailed info, see the bug database reference here . 有关更多详细信息,请参阅此处的错误数据库参考

The contract between equals() and compareTo() is that when equals() returns true, compareTo() should return 0 and when equals() is false compareTo should return -1 or +1. equals()和compareTo()之间的契约是当equals()返回true时,compareTo()应返回0,当equals()为false时,compareTo应返回-1或+1。

BTW: I assume your compare() method is not called very often as the debug messages will use up a signficiant amount of CPU and memory. 顺便说一句:我认为你的compare()方法不经常被调用,因为调试消息会占用大量的CPU和内存。

I agreed with all answer specially with jon, but one addinal things I want to tell that we should always check for null safety in compare method so that our method never be break and it's good habit in programming for always null checking. 我特别赞同jon的所有答案,但是我想告诉我们应该总是在比较方法中检查null安全性,这样我们的方法永远不会破坏,并且在编程中总是空检查是个好习惯。 For more info look here 有关详细信息,请查看此处

maybe you just have NaN values which you compare through Collections.sort... this has been a problem to me and i got that exception even having right implementation of compare(obj1, obj2) method! 也许你只有你通过Collections.sort比较的NaN值......这对我来说是一个问题,即使正确实施了compare(obj1,obj2)方法,我也得到了这个例外! Check that! 检查一下!

I got the same problem today in a web application. 我今天在Web应用程序中遇到了同样的问题。 Four calls working on the same array tried to sort it at the same time, effectively messing up for each other. 在同一个阵列上进行的四次调用试图同时对它进行排序,有效地相互混淆。

My solution: When I want to sort numbers and an array element is null, I put 0 then the error disappears. 我的解决方案:当我想对数字进行排序并且数组元素为空时,我输入0然后错误消失。 It is needed to take care that the sizes of each row in the two-dimensional arrays are the same. 需要注意二维阵列中每行的大小是相同的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM