Reputation: 17648
What are the "worst case" consequences (real world scenarios here), if I have an object (i.e. a bean) which has a solid, meaningful equals()
method, but lacks a complementary hashCode()
method? It seems like most APIs use the equals()
and compareTo()
methods for maintaining collections. I'm wondering when is the hashCode()
most important?
Upvotes: 2
Views: 289
Reputation: 718678
The worst-case consequences are that the hash table won't work. For example, lets assume that you've got a simple class like this:
public class StringWrapper {
private String value;
...
public boolean equals(Object other) {
// two objects are equal if their respective values are equal ... using `equals`.
}
// No hashcode override.
}
Here we have a class we have a class does not obey one of the required invariants of the equals/hashcode contract. Specifically, two instances cal be equal, but have different hashcodes.
When you add two different instances of this class to a HashSet, you may end up with both instances in the set ... on different hash chains. You get similar anomalies when removing objects from the set, testing to see if the set contains an object, and so on.
(Note that you may get lucky, and have the two instances end up on the same hash chain despite having different hashcodes. But your luck could change when some other unrelated object is added to the hash table, causing it to automatically resize. The resize is liable to cause entries with different hashcodes to be redistributed to different hash chains.)
So I'm wondering... when is the hashcode most important ?
It is always important.
Or to put it another way, it is only unimportant when you know with 100% certainty that instances of the class are never ever going to be used in hash tables. (And I don't know how you can know that, unless you delete all copies of the class. And that renders the whole question moot!)
UPDATE
@supercat mentioned the case where you can't write a decent hashcode.
If there is some good reason you can't write a half-decent hashcode()
method, I'd advocate overriding it to throw UnsupportedOperationException
or some such. That way you get a fast-fail if someone tries to put an instance into a hash table ... rather than a mysterious performance black-hole. (I would NOT recommend returning a constant hashcode.)
There is a related scenario where you might do this: when the object is inherently mutable, and you want to avoid the badness that happens if you mutate a hash key so that its hashcode changes.
Upvotes: 6
Reputation: 18568
This method returns the hash code value for the object on which this method is invoked. This method returns the hash code value as an integer and is supported for the benefit of hashing based collection classes such as Hashtable, HashMap, HashSet etc. This method must be overridden in every class that overrides the equals method.
Upvotes: 0
Reputation: 28687
If you're going to be concerned with either of these, you really, really should (need) to implement / override both. See Why do I need to override the equals and hashCode methods in Java? for specifics, including what can happen if these aren't implemented with proper, related implementations.
Additionally, from another answer there:
You must override hashCode() in every class that overrides equals(). Failure to do so will result in a violation of the general contract for Object.hashCode(), which will prevent your class from functioning properly in conjunction with all hash-based collections, including HashMap, HashSet, and Hashtable.
from Effective Java, by Joshua Bloch
Upvotes: 1