Java equals() and hashCode() methods are present in Object class. So every java class gets the default implementation of equals() and hashCode(). In this post we will look into java equals() and hashCode() methods in detail.
Object class defined equals() method like this:
public boolean equals(Object obj) {
return (this == obj);
}
According to java documentation of equals() method, any implementation should adhere to following principles.
x.equals(x)
should return true
.x.equals(y)
should return true
if and only if y.equals(x)
returns true
.x.equals(y)
returns true
and y.equals(z)
returns true
, then x.equals(z)
should return true
.x.equals(y)
should return same result, unless any of the object properties is modified that is being used in the equals()
method implementation.true
only when both the references are pointing to same object.Java Object hashCode() is a native method and returns the integer hash code value of the object. The general contract of hashCode() method is:
Java hashCode() and equals() method are used in Hash table based implementations in java for storing and retrieving data. I have explained it in detail at How HashMap works in java? The implementation of equals() and hashCode() should follow these rules.
o1.equals(o2)
, then o1.hashCode() == o2.hashCode()
should always be true
.o1.hashCode() == o2.hashCode
is true, it doesn’t mean that o1.equals(o2)
will be true
.When we override equals() method, it’s almost necessary to override the hashCode() method too so that their contract is not violated by our implementation. Note that your program will not throw any exceptions if the equals() and hashCode() contract is violated, if you are not planning to use the class as Hash table key, then it will not create any problem. If you are planning to use a class as Hash table key, then it’s must to override both equals() and hashCode() methods. Let’s see what happens when we rely on default implementation of equals() and hashCode() methods and use a custom class as HashMap key.
package com.journaldev.java;
public class DataKey {
private String name;
private int id;
// getter and setter methods
@Override
public String toString() {
return "DataKey [name=" + name + ", id=" + id + "]";
}
}
package com.journaldev.java;
import java.util.HashMap;
import java.util.Map;
public class HashingTest {
public static void main(String[] args) {
Map<DataKey, Integer> hm = getAllData();
DataKey dk = new DataKey();
dk.setId(1);
dk.setName("Pankaj");
System.out.println(dk.hashCode());
Integer value = hm.get(dk);
System.out.println(value);
}
private static Map<DataKey, Integer> getAllData() {
Map<DataKey, Integer> hm = new HashMap<>();
DataKey dk = new DataKey();
dk.setId(1);
dk.setName("Pankaj");
System.out.println(dk.hashCode());
hm.put(dk, 10);
return hm;
}
}
When we run above program, it will print null
. It’s because Object hashCode() method is used to find the bucket to look for the key. Since we don’t have access to the HashMap keys and we are creating the key again to retrieve the data, you will notice that hash code values of both the objects are different and hence value is not found.
We can define our own equals() and hashCode() method implementation but if we don’t implement them carefully, it can have weird issues at runtime. Luckily most of the IDE these days provide ways to implement them automatically and if needed we can change them according to our requirement. We can use Eclipse to auto generate equals() and hashCode() methods. Here is the auto generated equals() and hashCode() method implementations.
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
DataKey other = (DataKey) obj;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
Notice that both equals() and hashCode() methods are using same fields for the calculations, so that their contract remains valid. If you will run the test program again, we will get the object from map and program will print 10. We can also use Project Lombok to auto generate equals and hashCode method implementations.
In very simple terms, Java Hash table implementations uses following logic for get and put operations.
Below image shows a bucket items of HashMap and how their equals() and hashCode() are related. The phenomenon when two keys have same hash code is called hash collision. If hashCode() method is not implemented properly, there will be higher number of hash collision and map entries will not be properly distributed causing slowness in the get and put operations. This is the reason for prime number usage in generating hash code so that map entries are properly distributed across all the buckets.
We have already seen above that if hashCode() is not implemented, we won’t be able to retrieve the value because HashMap use hash code to find the bucket to look for the entry. If we only use hashCode() and don’t implement equals() then also value will be not retrieved because equals() method will return false.
You can download the complete code from our GitHub Repository.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
GReat Article, the best I have read. Thank you very much!!!
- javier
What do you mean with “bucket” and “key” ? What do you mean by “their contract” will not be “violated” ? Lastly, (sorry, I’m still learning) you define the methods, but where is it actually going to be used by the program to compare if objects are the same, and what will it do if it is not the same ? thank you!
- Henk
Clear explanation. Thank you very much! Is hash collision a bug in Java ? Thank you!
- Jan
Very good explanation of equals and hascode
- Venkat
Simple yet sophisticated. This really is the best article I have came across throughout a boatload of articles on the internet. Appreciate the efforts mate.
- Rajratna
Thank you… this is best one… you always share best and unique knowledge . Thanks
- Mukund
Thanks. Hat’s off to your effort.
- Saradindu Mazumder
Best one!
- Ankit