Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determining object equivalence using hash code

Let's say I have a simple class that represents a game tile, called Tile:

public class Tile {

    public final int x;
    public final int y;
    public final int plane;

    public Tile(int x, int y, int plane) {
        this.x = x;
        this.y = y;
        this.plane = plane;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        } else if (obj instanceof Tile) {
            Tile other = (Tile) obj;
            return other.x == x && other.y == y && other.plane == plane;
        }
        return false;
    }

    @Override
    public int hashCode() {
        return Objects.hash(x, y, plane);
    }
}

Being a responsible citizen, I implemented the hashCode method to make sure hash codes of equivalent objects are equal, per contract of equals. Then I was thinking, for any two Tile objects that have the same values for the x, y, and plane fields, the hash codes - as they should - will be equal. So why not just use that to check if objects are equivalent, rather than individually comparing the values of the fields?

More explicitly, why not replace:

@Override
public boolean equals(Object obj) {
    if (obj == this) {
        return true;
    } else if (obj instanceof Tile) {
        Tile other = (Tile) obj;
        return other.x == x && other.y == y && other.plane == plane;
    }
    return false;
}

with simply:

@Override
public boolean equals(Object obj) {
    return obj == this || obj != null && obj.hashCode() == hashCode();
}

Part of me feels that this is bad practice. This almost feels like circular reasoning. However, I cannot think of a valid, practical reason as to why this would be a bad practice.

In short: is it appropriate to use the result of hashCode to determine the result of equals?

like image 350
Martin Tuskevicius Avatar asked Feb 15 '26 23:02

Martin Tuskevicius


2 Answers

No. Think of it as follows: there are 2^32 * 2^32 * 2^32 = 2^96 different possible Tiles, for each combination of three ints.

There are only 2^32 possible hashCodes.

So for any given Tile there will be 2^64 different possible Tiles with the same hash code.

In short: hash codes are not unique. Many objects will happen to have the same hash code even though they're not equal.

(In general, always remember that return 0; is a valid implementation of hashCode().)

like image 182
Louis Wasserman Avatar answered Feb 17 '26 20:02

Louis Wasserman


See the contract of hashCode():

It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results.

Two "equal" objects should have the same hash code.

Two "unequal" objects can have the same hash code.

like image 33
Matthieu Avatar answered Feb 17 '26 22:02

Matthieu



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!