Relationship between hashCode and equals method in Java [duplicate]
Asked Answered
T

7

116

I read in many places saying while override equals method in Java, should override hashCode method too, otherwise it is "violating the contract".

But so far I haven't faced any problem if I override only equals method, but not hashCode method.

What is the contract? And why am I not facing any problem when I am violating the contract? In which case will I face a problem if I haven't overridden the hashCode method?

Transmundane answered 10/6, 2013 at 15:44 Comment(2)
The thing about this "contract" is that nothing enforces it. If you break it, nothing breaks immediately. But other code that handles your objects is free to "break", if you don't follow your part of the contract. And that's exactly what happens when you try to use such objects in a HashMap.Oquendo
javaworld.com/article/2074996/…Ichthyosis
T
163

The problem you will have is with collections where unicity of elements is calculated according to both .equals() and .hashCode(), for instance keys in a HashMap.

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

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

The part of the contract here which is important is: objects which are .equals() MUST have the same .hashCode().

This is all documented in the javadoc for Object. And Joshua Bloch says you must do it in Effective Java. Enough said.

Trina answered 10/6, 2013 at 15:47 Comment(4)
Short and "Nuff said" +1Filicide
@Trina I have one confusion, why do we need to override equals method when we override hashCode method in case of HashMap? . In anycase hashmap replace the value if object's hashcode is equal.Forewing
@VikasVerma no it doesn't; first, the hash code of the key is calculated, the correct bucket is then queried for equality. If you don't override .equals(), you may be in a situation where two objects with the same hash code are not equal, since the default implementation of .equals() is reference equality (ie, ==).Trina
There is a corollary: if there are hash collisions then the return of equals() has priority.Zandra
D
17

According to the doc, the default implementation of hashCode will return some integer that differ for every object

As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation
technique is not required by the JavaTM programming language.)

However some time you want the hash code to be the same for different object that have the same meaning. 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 kind of problem will be occur if you use a hash data structure in the collection framework such as HashTable, HashSet. Especially with collection such as HashSet you will end up having duplicate element and violate the Set contract.

Decker answered 10/6, 2013 at 15:52 Comment(0)
P
11

Yes, it should be overridden. If you think you need to override equals(), then you need to override hashCode() and vice versa. The general contract of hashCode() is:

  1. Whenever it 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. This integer need not remain consistent from one execution of an application to another execution of the same application.

  2. If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.

  3. It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.

Packing answered 10/6, 2013 at 15:47 Comment(0)
S
8

Have a look at Hashtables, Hashmaps, HashSets and so forth. They all store the hashed key as their keys. When invoking get(Object key) the hash of the parameter is generated and lookup in the given hashes.

When not overwriting hashCode() and the instance of the key has been changed (for example a simple string that doesn't matter at all), the hashCode() could result in 2 different hashcodes for the same object, resulting in not finding your given key in map.get().

Sigismond answered 10/6, 2013 at 15:49 Comment(0)
C
7

The contract is that if obj1.equals(obj2) then obj1.hashCode() == obj2.hashCode() , it is mainly for performance reasons, as maps are mainly using hashCode method to compare entries keys.

Cylindroid answered 10/6, 2013 at 15:48 Comment(2)
if obj1 != obj2then obj1.hasCode() != obj2.hashCode() <-- not true! They MAY have different hash codes but this is not a requirementTrina
@Trina you're right, hashCodes can collide, I editCylindroid
L
6

See JavaDoc of java.lang.Object

In hashCode() it says:

If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.

(Emphasis by me).

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

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

Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.

Linnet answered 10/6, 2013 at 15:49 Comment(0)
G
5

A contract is: If two objects are equal then they should have the same hashcode and if two objects are not equal then they may or may not have same hash code.

Try using your object as key in HashMap (edited after comment from joachim-sauer), and you will start facing trouble. A contract is a guideline, not something forced upon you.

Gander answered 10/6, 2013 at 15:46 Comment(1)
"should have" => "must have", and you should mention "Try using them as keys in a HashMap".Oquendo

© 2022 - 2024 — McMap. All rights reserved.