davidxxx
davidxxx

Reputation: 131546

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. 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

Answers (1)

fabian
fabian

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

Related Questions