I'm writing an isometric game that renders objects based on their Y coordinate, using a comparable class, sorting by their Y value, which changes. I am getting the error "Comparison method violates its general contract!" and have read about how to return a negative number, 0, or a positive number so I have implemented this:
public boolean equals(Entity e) {
if ((e.y-y)==0)
return (e.id == id);
return (e.y == y);
}
public int compareTo(Entity e) {
if ((e.y-y)==0)
return (e.id - id);
return (int) (e.y - y); // Render order by y coordinate
}
But I'm still getting the error. Is the sorting not going to work if the values change or am I doing something else wrong?
The equals
method is not involved in the contract, so we can ignore it.
I suspect that the problem is caused by integer overflow. The problem is that x - y
does not always give you a positive answer if x > y
and a negative number if x < y
. If the difference between the numbers is large enough, then the express x - y
will overflow and the result will have the wrong sign.
If that is the problem, then the simple solution is to use Integer.compare(x, y)
instead of x - y
Another possibility is that the entities are being mutated at the same time as you are (for example) sorting them.
Float.compare(x, y) has worked much better.
I'd assumed that x
and y
were int
. If they are float
then the true cause of the problem is harder to understand. Either way, using Float.compare(x, y)
is a better solution.
But if x
and y
are actually int
, then using Float.compare(x, y)
will give you incorrect answers for some x
and y
values. For close values of x
and y
with large enough magnitudes, the int
to float
conversion will lose precision, and Float.compare
will say they are equal.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With