Reputation: 131546
A java.lang.IllegalArgumentException: Comparison method violates its general contract!
is thrown when I do a Collections.sort()
with a List of ISimulationResultSet
.
I have not found the reason why contract is not respected.
If someone has a idea of the reason, it will be great to explain.
This is the Comparator I am using :
public int compare(ISimulationResultSet r1, ISimulationResultSet r2) {
final float r1Esperance = r1.getResults().getEsperanceGainOuPerte();
final float r2Esperance = r2.getResults().getEsperanceGainOuPerte();
final float r1PrctCibleAtteinte = r1.getResults().getPrctCibleAtteinte();
final float r2PrctCibleAtteinte = r2.getResults().getPrctCibleAtteinte();
if (r1Esperance / r2Esperance > 1.05F)
return -1;
else if (r1Esperance / r2Esperance < 0.95F) {
return 1;
}
else {
if (r1PrctCibleAtteinte == r2PrctCibleAtteinte) {
if (r1Esperance > r2Esperance)
return -1;
else if (r1Esperance < r2Esperance)
return 1;
return 0;
}
else if (r1PrctCibleAtteinte > r2PrctCibleAtteinte)
return -1;
else if (r1PrctCibleAtteinte < r2PrctCibleAtteinte)
return 1;
}
return 0;
}
Upvotes: 0
Views: 136
Reputation: 82531
The comparator has to be symetric, i.e. sgn(compare(x, y)) == -sgn(compare(y, x))
(sgn
being the signum function here). This is not the case for your comparator:
Let a1
and a2
denote the values of x.getResults().getEsperanceGainOuPerte()
and y.getResults().getEsperanceGainOuPerte()
respectively and let b1
and b2
denote the values of x.getResults().getPrctCibleAtteinte()
and y.getResults().getPrctCibleAtteinte()
respectively.
Now consider the following:
1.05 < a1 < 1.052
a2 = 1
b2 > b1
Therefore a2 / a1 > 0.95
compare(x, y) == -1;// first (r1Esperance / r2Esperance > 1.05F) is true
compare(y, x) == -1; // first 3 conditions false, (r1PrctCibleAtteinte > r2PrctCibleAtteinte) is true
That violates the contract.
Upvotes: 4