bn.
bn.

Reputation: 7949

Is checking hashCode() equality a valid approach to implement equals(Object obj)?

My hashCode method ensures that equal objects have equal hash codes. My implementation also guarantees that the contrapositive is true, in that equal hash codes imply object equality. Doing something like:

   @Override
    public boolean equals(Object obj) {
        if (this == obj) {return true;}
        if (obj == null) {return false;}
        if (getClass() != obj.getClass()) {return false;}
        return (obj.hashCode() == this.hashCode());
    }

seems an obvious choice, but I don't see this often. Is this is a good idea in my case, or am I missing something?

Also, I'm not sure if this is relevant, but the hashCode and equals methods are in generated classes (and obviously are themselves generated). The reason I mention this is to highlight the fact that these methods will not be maintained manually per say. They are in classes that are created at compile time and are not intended to be changed unless the schema they are based on changes.

Upvotes: 2

Views: 346

Answers (5)

Romski
Romski

Reputation: 1942

No, the hash is used to distribute your objects in a collection, they are not unique. For example, a collection would use the hashcode to identify a bucket to place your object. The bucket itself is a List of all objects with similar hash codes. The purpose is for efficiency in lookups where order is unimportant.

It is important to build your hash using the same attributes for equality to ensure that 2 semantically equal objects end up in the same bucket

Upvotes: -2

murgatroid99
murgatroid99

Reputation: 20297

If, as the question says, your hashCode implementation really does guarantee that unequal objects have unequal hash codes, then in principle there is nothing wrong with what you are doing. Your equals method is checking a property that is equivalent to equality, so the behavior is as intended. You should re-check that guarantee, though; remember that no matter how clever you are, you can only store 32 bits of information in an int, which means that most non-trivial objects will necessarily have hash colisions.

However, there are a few caveats. First is clarity: if you implement equals this way, anyone using your code has to look at your hashCode implementation to find out what properties determine equality. Second is speed: if your hash code implementation is significantly slower than simply checking equality of the relevant properties (including boolean shortcutting in that calculation), then it may be worth re-implementing the logic in the equals function to avoid the speed penalty. Third is coupling: implementing equals in this manner means that it depends on that property of hashCode, and any future change to hashCode has to either preserve that property or move the logic into equals.

Upvotes: 6

rossum
rossum

Reputation: 15693

If, and only if, your contrapositive guarantee holds then you can test equality that way. In the general case your contrapositive does not hold and equality is not guaranteed. In particular someone may override the hashCode() method so your contrapositive no longer holds. Far better to use a more traditional equality test which compares significant fields.

Your code is fragile, and depends critically on a very specific property of your hashCode() implementation which is not part of the general hashCode() contract. You can always use non-matching hash codes to detect inequality. It is not good practice to use equal hash codes to assume equality.

Upvotes: 2

Brett Okken
Brett Okken

Reputation: 6306

This is not a good idea. While two objects which are equal must have the same hash code, the opposite is not true: 2 objects with the same hash code may not be equal. As a simple example, consider Long. The hash code returns an int, so it is not possible to represent with an int all possible long values. This means that many Long objects are not equal, but have the same hash code.

Upvotes: 4

The Velcromancer
The Velcromancer

Reputation: 447

Sometimes (though rarely), hash codes can result in collisions; you are probably aware of this!

As a result of that, it's a good idea to base equality on other features of the objects being compared (perhaps in addition to the hash code).

Upvotes: -1

Related Questions