Tutorial

Java equals() and hashCode()

Published on August 3, 2022
author

Pankaj

Java equals() and hashCode()

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.

Java equals()

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.

  • For any object x, x.equals(x) should return true.
  • For any two object x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
  • For multiple objects x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
  • Multiple invocations of x.equals(y) should return same result, unless any of the object properties is modified that is being used in the equals() method implementation.
  • Object class equals() method implementation returns true only when both the references are pointing to same object.

Java hashCode()

Java Object hashCode() is a native method and returns the integer hash code value of the object. The general contract of hashCode() method is:

  • Multiple invocations of hashCode() should return the same integer value, unless the object property is modified that is being used in the equals() method.
  • An object hash code value can change in multiple executions of the same application.
  • 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.

Importance of equals() and hashCode() method

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.

  • If o1.equals(o2), then o1.hashCode() == o2.hashCode() should always be true.
  • If o1.hashCode() == o2.hashCode is true, it doesn’t mean that o1.equals(o2) will be true.

When to override equals() and hashCode() methods?

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.

Implementing equals() and hashCode() method

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. eclipse generate hashCode and equals method 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.

What is Hash Collision

In very simple terms, Java Hash table implementations uses following logic for get and put operations.

  1. First identify the “Bucket” to use using the “key” hash code.
  2. If there are no objects present in the bucket with same hash code, then add the object for put operation and return null for get operation.
  3. If there are other objects in the bucket with same hash code, then “key” equals method comes into play.
    • If equals() return true and it’s a put operation, then object value is overridden.
    • If equals() return false and it’s a put operation, then new entry is added to the bucket.
    • If equals() return true and it’s a get operation, then object value is returned.
    • If equals() return false and it’s a get operation, then null is returned.

Below image shows a bucket items of HashMap and how their equals() and hashCode() are related. java hashmap, how hashmap works in java 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.

What if we don’t implement both hashCode() and equals()?

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.

Best Practices for implementing equals() and hashCode() method

  • Use same properties in both equals() and hashCode() method implementations, so that their contract doesn’t violate when any properties is updated.
  • It’s better to use immutable objects as Hash table key so that we can cache the hash code rather than calculating it on every call. That’s why String is a good candidate for Hash table key because it’s immutable and cache the hash code value.
  • Implement hashCode() method so that least number of hash collision occurs and entries are evenly distributed across all the buckets.

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.

Learn more about our products

About the authors
Default avatar
Pankaj

author

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.

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
JournalDev
DigitalOcean Employee
DigitalOcean Employee badge
October 23, 2020

GReat Article, the best I have read. Thank you very much!!!

- javier

    JournalDev
    DigitalOcean Employee
    DigitalOcean Employee badge
    June 29, 2020

    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

      JournalDev
      DigitalOcean Employee
      DigitalOcean Employee badge
      March 8, 2020

      Clear explanation. Thank you very much! Is hash collision a bug in Java ? Thank you!

      - Jan

        JournalDev
        DigitalOcean Employee
        DigitalOcean Employee badge
        November 12, 2019

        Very good explanation of equals and hascode

        - Venkat

          JournalDev
          DigitalOcean Employee
          DigitalOcean Employee badge
          October 15, 2019

          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

            JournalDev
            DigitalOcean Employee
            DigitalOcean Employee badge
            August 24, 2019

            Thank you… this is best one… you always share best and unique knowledge . Thanks

            - Mukund

              JournalDev
              DigitalOcean Employee
              DigitalOcean Employee badge
              June 22, 2019

              Thanks. Hat’s off to your effort.

              - Saradindu Mazumder

                JournalDev
                DigitalOcean Employee
                DigitalOcean Employee badge
                June 1, 2019

                Best one!

                - Ankit

                  Try DigitalOcean for free

                  Click below to sign up and get $200 of credit to try our products over 60 days!

                  Sign up

                  Join the Tech Talk
                  Success! Thank you! Please check your email for further details.

                  Please complete your information!

                  Become a contributor for community

                  Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

                  DigitalOcean Documentation

                  Full documentation for every DigitalOcean product.

                  Resources for startups and SMBs

                  The Wave has everything you need to know about building a business, from raising funding to marketing your product.

                  Get our newsletter

                  Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

                  New accounts only. By submitting your email you agree to our Privacy Policy

                  The developer cloud

                  Scale up as you grow — whether you're running one virtual machine or ten thousand.

                  Get started for free

                  Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

                  *This promotional offer applies to new accounts only.