or "Why do the Sun/Oracle guys force us to override both equals() and hashCode() everytime?"
Everyone knows that, if you override equals() or hashCode() of an object, you have to override the other one, too, because there is a contract between those two:
Note that it is generally necessary to override the hashCode method whenever this method [i.e. equals()] is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes. -- API doc of Object.equals()
Why isn't it implemented that way in the Object class:
public boolean equals(Object obj) {
return this.hashCode() == obj.hashCode()
}
If they did this, it would have saved the rest of the world from having to implement both methods. It would be enough to override only hashCode().
I guess the guys had some good reason not to do this. I just cannot see it - please clear this up for me.
Technically, yes, you can only implement equals() method without implementing hashcode() method. But that would be a breach of contract. The standard practice says that you should implement both of them and for the equal object the hashcode should be the same.
If two objects are equal according to equals() method, then their hash code must be same. If two objects are unequal according to equals() method, their hash code are not required to be different. Their hash code value may or may-not be equal.
Case 1: Overriding both equals(Object) and hashCode() method Whenever it(hashcode) is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified.
Both methods, equals() and hashcode() , are used in Hashtable , for example, to store values as key-value pairs. If we override one and not the other, there is a possibility that the Hashtable may not work as we want, if we use such object as a key.
If a.equals(b)
returns true then a.hashCode() == b.hashCode()
must evaluate to true
.
The opposite is not true! It's perfectly valid to have two objects where a.hashCode() == b.hashCode()
is true, but a.equals(b)
is false.
In fact, that's necessary. There are 232 possible return values for hashCode()
. At any given moment a JVM can hold more than 232 objects (given there's enough memory, which is quite possible these days). Assuming that none of the objects are equal to each other (easy to do, just let them be "s1"
, "s2"
, ...), then you're bound to have a collision of checksums (see Pidgeonhole principle).
In fact, this is the simplest possible hashCode
implementation that's correct (but otherwise terribly bad) for every class*:
public int hashCode() {
return 0;
}
It magically fulfills all the requirements of the general hashCode()
contract.
* except for those classes that have a defined and documented hashCode
algorithm that they must implement, the prime example being String.hashCode()
.
Joachim is correct, but there's another reason: Efficiency.
Calculating a hash code can be expensive, and this effort would be unnecessarily incurred if equals()
was invoked, but hashCode()
never was.
There are lots of cases where this would be the case; only classes like Hashtable
(or those that use it) invoke hashCode()
.
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