davidxxx - 1 month ago 5
Java Question

Exception during Collections.sort()

A

`java.lang.IllegalArgumentException: Comparison method violates its general contract!`
is thrown when I do a
`Collections.sort()`
with a List of
`ISimulationResultSet`
.
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;
}
``````

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.

Source (Stackoverflow)