asteri
asteri

Reputation: 11592

Collections.sort() works, but Collections.reverseOrder() breaks

So I've got a line of code like the following:

Collections.sort(lists, new SpecificComparator());

Works fine. But when I try to get it in descending order...

Collections.sort(lits, Collections.reverseOrder(new SpecificComparator()));

... it breaks with the following Exception:

java.lang.IllegalArgumentException: Comparison method violates its general contract!

When I searched for the Exception message, I found this Q&A, stating that it was because the relationship was not transitive. I guess I'm a little confused on how a relationship can be transitive in one direction and not in the other. My understanding of transitivity is A == B && B == C -> A == C, so...

Here's my comparator:

public class SuperComparator implements Comparator<Item> {

    @Override
    public int compare(Item first, Item second) {
        Result a = first.getResult();
        Result b = second.getResult();
        if(a == null && b == null) return 0;
        if(b == null || b == Result.DISQUALIFIED) return 1;
        if(a == null || a == Result.DISQUALIFIED) return -1;
        return b.getIntValue() - a.getIntValue();
    }

}

...

public class SpecificComparator extends SuperComparator {

    @Override
    public int compare(Item first, Item second) {

        int rank = super.compare(first, second);

        if(rank != 0) return rank;

        BigDecimal thisAmount = first.getAmount() != null ? first.getAmount() : BigDecimal.ZERO;
        BigDecimal otherAmount = second.getAmount() != null ? second.getAmount() : BigDecimal.ZERO;

        return thisAmount.compareTo(otherAmount);
    }

Upvotes: 2

Views: 242

Answers (2)

ngasull
ngasull

Reputation: 4216

Your comparator is certainly not transitive.

Ensure that for 3 items A, B and C, if A > B and B > C, then A > C ; then you'll be fine

Upvotes: 1

user902383
user902383

Reputation: 8640

If both of your items are disqualified, your comparator will always return 1, and that is wrong.

add check for case when both your items are disqualified and your problem will be solved

Upvotes: 4

Related Questions