Reputation: 7949
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
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
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
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
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
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