Sayed Hassan Sayed Hassan - 3 months ago 11
Java Question

Collections.sort - IllegalArgumentException: Comparison method violates its general contract

Some of our users are getting this exception while sorting a list. The code that throws it is

Collections.sort(activeConverstions, new Comparator<Conversation>() {
@Override
public int compare(Conversation o1, Conversation o2) {
return (int)(o2.getTime()- o1.getTime()); // descending order
}
});


while getTime() is of type "long"

Answer

The issue is probably casting a long to int, which may convert a large long number to a negative int.

For example, consider this snippet :

long first = Integer.MAX_VALUE + 1;
long second = 0;
System.out.println((int) (first - second));
System.out.println((int) (second - first));

Output :

-2147483648
-2147483648

If you would pass to your compare method two Conversation instances - let's call them x and y - whose getTime() is equal to first and second in the above snippet respectively, both compare(x,y) and compare(y,x) would return a negative value, which violates the contract of that method.

Try :

Collections.sort(activeConverstions, new Comparator<Conversation>() {
    @Override
    public int compare(Conversation o1, Conversation o2) {
        return o2.getTime() > o1.getTime() ? 1 :  o2.getTime() < o1.getTime() ? -1 : 0;
    }
});

or, as assylias suggested :

Collections.sort(activeConverstions, new Comparator<Conversation>() {
    @Override
    public int compare(Conversation o1, Conversation o2) {
        return Long.compare(o2,getT‌​ime(), o1.getTime());
    }
});
Comments