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

a 夏天 提交于 2019-11-26 11:30:06

问题


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)

The method sre.getSponsored() returns a boolean.

Thanks.


回答1:


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

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.




回答2:


I assume that you are using JDK 7. Check the following URL:

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

Area: API: Utilities

Synopsis: Updated sort behavior for Arrays and Collections may throw an IllegalArgumentException

Description: The sorting algorithm used by java.util.Arrays.sort and (indirectly) by java.util.Collections.sort has been replaced. The new sort implementation may throw an IllegalArgumentException if it detects a Comparable that violates the Comparable contract. 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

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




回答3:


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.

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.




回答4:


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




回答5:


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!




回答6:


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.




回答7:


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.



来源:https://stackoverflow.com/questions/6626437/why-does-my-compare-method-throw-exception-comparison-method-violates-its-gen

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!