Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the implementation of Object.equals() not using hashCode()?

Tags:

java

equals

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.

like image 659
Francois Bourgeois Avatar asked Aug 26 '13 14:08

Francois Bourgeois


People also ask

Can I implement equals without hashCode?

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.

Does equals method use hashCode?

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.

Why is it important to override hashCode () when you override equals () in Java?

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.

Why u need to implement hashCode and equals both?

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.


2 Answers

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().

like image 163
Joachim Sauer Avatar answered Sep 29 '22 12:09

Joachim Sauer


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().

like image 38
Bohemian Avatar answered Sep 29 '22 12:09

Bohemian