Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using comparable to compare different variables

I'm familiar with standard comparisons using the Comparable interface, although today I'm having some trouble when I want to compare several different variables.

I basically want to implement a compareTo method that yields the result -1 only when the following if statement is true:

if (o.maxX > minX && o.maxY > minY && o.minZ < maxZ)

Although, I'm not sure if this is possible using a comparable, or I'm just not as familiar with it as it seems. Because when I try the approach

public int compareTo(IsoSprite o) {
    if (o.maxX > minX && o.maxY > minY && o.minZ < maxZ){
        return -1;
    }else if(o.maxX < minX && o.maxY < minY && o.minZ > maxZ){
        return 1;
    }
    return 0;
}

I receive the error "Comparison method violates its general contract!". I want to clarify that I don't need help with understanding what this error means, because I've read several questions about it. Although, I still can't put my mind around this particular problem, because the solutions to the other questions that I've read have been trivial.

I would really appreciate some help with this comparison, it would be a life saver. Any input is also well appreciated.

Edit: After testing around, I have got something that almost works (not in all cases), but I can't figure out why:

public int compareTo(IsoSprite o) {
    if (o.maxX > minX && o.maxY > minY && o.minZ < maxZ) {
        return -1;
    } else if (o.maxX > minX && o.maxY > minY && o.minZ > maxZ) {
        return 1;
    }else if (o.maxX < minX && o.maxY > minY && o.minZ > maxZ) {
        return 1;
    }else if (o.maxX < minX && o.maxY < minY && o.minZ > maxZ) {
        return 1;
    }else if (o.maxX < minX && o.maxY > minY && o.minZ < maxZ) {
        return 1;
    }else if (o.maxX > minX && o.maxY < minY && o.minZ > maxZ) {
        return 1;
    }else if (o.maxX < minX && o.maxY < minY && o.minZ > maxZ) {
        return 1;
    }else if (o.maxX > minX && o.maxY < minY && o.minZ < maxZ) {
        return 1;
    }else if (o.maxX < minX && o.maxY > minY && o.minZ < maxZ) {
        return 1;
    }else if(this != o){
        return 1;
    }
    return 0;
}
like image 927
Deminth Avatar asked Oct 31 '22 02:10

Deminth


1 Answers

If you are using this to sort your objects, then your Comparable or Comparator must be well behaved and must respect the transitive and other rules. If not, then your code is broken. It is recommended that your comparing methods be consistent with equals, that means that a.compareTo(b) returns 0 if and only if a.equals(b), but unlike as was stated in a deleted answer, this is not an absolute requirement.

Your code still breaks a commutative like rule for comparing, namely that

a.compareTo(b) == -b.compareTo(a)

Let's look at your rules:

public int compareTo(IsoSprite o) {
    // Comparison A
    if (o.maxX > minX && o.maxY > minY && o.minZ < maxZ) {
        return -1;
    // Comparison B
    } else if (o.maxX > minX && o.maxY > minY && o.minZ > maxZ) {
        return 1;
    // Comparison C
    }else if (o.maxX < minX && o.maxY > minY && o.minZ > maxZ) {
        return 1;
    // Comparison D
    }else if (o.maxX < minX && o.maxY < minY && o.minZ > maxZ) {
        return 1;
    // Comparison E
    }else if (o.maxX < minX && o.maxY > minY && o.minZ < maxZ) {
        return 1;
    // Comparison F
    }else if (o.maxX > minX && o.maxY < minY && o.minZ > maxZ) {
        return 1;
    // Comparison G
    }else if (o.maxX < minX && o.maxY < minY && o.minZ > maxZ) {
        return 1;
    // Comparison H
    }else if (o.maxX > minX && o.maxY < minY && o.minZ < maxZ) {
        return 1;
    // Comparison I
    }else if (o.maxX < minX && o.maxY > minY && o.minZ < maxZ) {
        return 1;
    // Comparison J
    }else if(this != o){
        return 1;
    }
    return 0;
}

Look at "Comparison C":

}else if (o.maxX < minX && o.maxY > minY && o.minZ > maxZ) {

which returns 1. The converse of this should return -1, but it doesn't since we find the converse in "Comparison H":

}else if (o.maxX > minX && o.maxY < minY && o.minZ < maxZ) {

But it too returns 1. Thus here (and possibly elsewhere) a.compareTo(b) does not equal the - of b.compareTo(a).

like image 171
Hovercraft Full Of Eels Avatar answered Nov 04 '22 06:11

Hovercraft Full Of Eels