Java 为什么我的比较方法会抛出异常——比较方法违反了它的一般约定!

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6626437/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-16 08:22:10  来源:igfitidea点击:

why does my compare method throw exception -- Comparison method violates its general contract!

javaandroidcomparatorcontract

提问by lost baby

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)

The method sre.getSponsored() returns a boolean.

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

Thanks.

谢谢。

采纳答案by Jon Skeet

I suspect the problem occurs when neithervalue is sponsored. That will return 1 whichever way you call it, i.e.

我怀疑当两个价值都没有赞助时会出现问题。无论你怎么称呼它,这都会返回 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 actuallyextract 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,这将使代码更清晰。

回答by Peter Lawrey

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 和内存。

回答by naresh

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

Synopsis: Updated sort behavior for Arraysand Collectionsmay throw an IllegalArgumentException

Description: The sorting algorithm used by java.util.Arrays.sortand (indirectly) by java.util.Collections.sorthas been replaced. The new sort implementation may throw an IllegalArgumentExceptionif it detects a Comparablethat violates the Comparablecontract. 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.

Nature of Incompatibility: behavioral

RFE: 6804124

领域:API:公用事业

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

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

不相容的性质:行为

RFE:6804124

For more detailed info, see the bug database reference here.

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

回答by naresh

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! Check that!

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

回答by kailash gaur

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. For more info look here

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

回答by Bjarne Havnen

I got the same problem today in a web application. Four calls working on the same array tried to sort it at the same time, effectively messing up for each other.

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

回答by Eduardo Enrique Lopez Saucedo

My solution: When I want to sort numbers and an array element is null, I put 0 then the error disappears. It is needed to take care that the sizes of each row in the two-dimensional arrays are the same.

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