Reputation: 11592
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
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
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