Calgacus Calgacus - 1 month ago 10
Android Question

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)


The method sre.getSponsored() returns a boolean.

Thanks.

Answer

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.