5

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;
}
3
  • 1
    stackoverflow.com/questions/8327514/… the top answer might be useful Commented Jun 14, 2015 at 0:34
  • 3
    You know that your code violates Comparable's general contract (possibly by failing the transitivity rule), then it can't be used for sorting. Period. Your question may be an XY Problem where you ask how to solve a specific code problem when the best solution is to use a completely different approach. Better that you tell us the overall problem that you're trying to solve rather than how you're currently trying to solve it. Commented Jun 14, 2015 at 1:18
  • @HovercraftFullOfEels It's not only just this specific problem, I've ran into problems like this before too, it somehow seems like they could be solved with a comparable somehow Commented Jun 14, 2015 at 2:29

1 Answer 1

2

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

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.