The relationship between the hashCode method and equals in Java

I read in many places saying that overriding the equals method in Java must override the hashCode method, otherwise it will "break the contract."

But so far I have not encountered any problem if I override only the equals method and not the hashCode method.

What is a contract? And why am I not facing any problem when I break the contract? In this case, I would run into a problem if I did not override the hashCode method?

+61
java
Jun 10 '13 at 15:44
source share
7 answers

The problem that you will encounter is collections in which the uniqueness of the elements is calculated according to .equals() and .hashCode() , for example, in HashMap .

As its name suggests, it relies on hash tables, and hash buckets are a function of the .hashCode() object.

If you have two objects that have .equals() but have different hash codes, you lose!

Part of the contract is important here: objects that .equals() MUST have the same .hashCode() .

All of this is described in javadoc for Object . And Joshua Bloch says you have to do it in Effective Java . Enough said.

+93
Jun 10 '13 at 15:47
source share

According to the document, the hashCode implementation by default returns an integer that is different for each object

As far as reasonably practical, the hashCode method defined by the Object class returns different integers for different objects. (Usually this is implemented by converting the internal address of the object to an integer, but this implementation
the method is not required by the JavaTM programming language.)

However, for some time you want the hash code to be the same for different objects that have the same value. for example

 Student s1 = new Student("John", 18); Student s2 = new Student("John", 18); s1.hashCode() != s2.hashCode(); // With the default implementation of hashCode 

This problem occurs if you use a hash data structure within the collection, such as HashTable, HashSet. Specifically for a collection like HashSet, you will get a duplicate element and break the Set contract.

+8
Jun 10 '13 at 15:52
source share

Yes, this should be canceled. If you think you need to override equals() , you need to override hashCode() and vice versa. General hashCode () contract:

  • Whenever it is called on the same object more than once during the execution of a Java application, the hashCode method must consistently return the same integer if the information used in equal comparisons with the object does not change. This integer should not remain consistent with one execution of the application on another execution of the same application.

  • If two objects are equal in accordance with the equals (Object) method, then calling the hashCode method for each of the two objects should give the same result of the whole.

  • It is not required that if two objects are unequal according to the equals method (java.lang.Object), then calling the hashCode method for each of the two objects must produce different integer results. However, the programmer should be aware that creating separate integer results for unequal objects can improve the performance of hash tables.

+6
Jun 10 '13 at 15:47
source share

Contract: if two objects are equal, then they must have the same hash code, and if two objects are not equal, then they may or may not have the same hash code.

Try using your object as a key in HashMap (edited after a comment from joachim-sauer), and you will begin to run into problems. A contract is a guide, not something imposed on you.

+3
Jun 10 '13 at 15:46
source share

See JavaDoc java.lang.Object

hashCode() says:

If two objects are equal in accordance with the equals(Object) method, then calling the hashCode method for each of the two objects should produce the same integer result .

(Emphasize me).

If you override only equals() and not hashCode() , your class violates this contract.

This is also said in the JavaDoc of the equals() method:

Note that it is usually necessary to override the hashCode method when this method is overridden in order to maintain a common contract for the hashCode method, which states that equal objects must have the same hash codes.

+3
Jun 10 '13 at 15:49
source share

Take a look at Hashtables, Hashmaps, HashSets, etc. They all store the hashed key as their keys. When get (object key) is called, the hash of the parameter is generated and viewed in these hashes.

If you do not rewrite hashCode () and the key instance has been changed (for example, a simple string that does not matter at all), hashCode () can lead to two different hash codes for the same object, as a result of which the key cannot be found in map.get ().

+3
Jun 10 '13 at 15:49
source share

The contract is that if obj1.equals(obj2) then obj1.hasCode() == obj2.hashCode() , this is mainly for performance reasons, since maps mostly use hashCode to compare record keys.

+2
Jun 10 '13 at 15:48
source share



All Articles