Blog Java

Understanding equals() and hashCode() in Java

Introduction

In Java, equals() and hashCode() are two fundamental methods present in the Object class which are used for comparing object equality and for use in collections, respectively. It’s a common practice to override these methods in your own classes, especially if you want to compare object equality based on their logical state rather than their identity.

The equals() Method

The equals() method is used to determine the equality of two objects.

Java
public boolean equals(Object obj)

This method checks if some other object passed to it as an argument is “equal to” the object on which this method is invoked.

Here’s an example:

Java
String str1 = new String("Hello");
String str2 = new String("Hello");

System.out.println(str1.equals(str2));  // Output: true

Even though str1 and str2 refer to two different objects, the equals() method returns true. This is because the String class overrides the equals() method of the Object class for its own specific implementation.

The hashCode() Method

The hashCode() method returns an integer hash code representing the object.

Java
public int hashCode()

The general contract of hashCode is that 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.

Here’s an example:

String str1 = new String("Hello");
String str2 = new String("Hello");

System.out.println(str1.hashCode());  // Output: 69609650
System.out.println(str2.hashCode());  // Output: 69609650

As you can see, since str1 and str2 are equal according to the equals() method, their hash codes are also the same.

Importance of equals() and hashCode()

Here’s a simple example of how you might override equals() and hashCode() in a Person class:

Java
public class Person {
    private String name;
    private int age;

    // constructor, getters and setters...

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        Person person = (Person) obj;
        return age == person.age && name.equals(person.name);
    }

    @Override
    public int hashCode() {
        int result = name.hashCode();
        result = 31 * result + age;
        return result;
    }
}

In this example:

  • The equals() method checks if the passed object is of the same type and then compares the name and age fields for equality.
  • The hashCode() method returns a hash value that is a combination of the hash values of the name and age fields. The number 31 is used as a multiplier because it’s an odd prime number, which helps in evenly distributing the hash values.

Remember, when you override equals(), you should also override hashCode(), and vice versa. This is because Java collections like HashSetHashMap, etc. rely on both methods for correctly storing and retrieving objects.

The hashCode() method in Java is a part of the Object class and is used primarily in conjunction with collections, like HashMapHashSet, and HashTable.

Here are some key points about hashCode():

  1. Hashing Mechanism: It provides a hashing mechanism where it takes information from the object and converts it into an integer. This integer is used for determining the bucket location when storing the object in a hashed collection.
  2. Performance Improvement: Using hashCode() improves performance while retrieving elements from large collections. It’s much faster to use a hash code to look up an object in a HashMap than it would be to search the object sequentially.
  3. Contract with Equals: There’s a contract between equals() and hashCode() that if two objects are equal according to the equals() method, then calling hashCode() on each of the two objects must return the same integer result. This is why when you override equals(), you should also override hashCode().
  4. Uniqueness Not Guaranteed: While hashCode() is used to provide a unique identifier for the object, it doesn’t guarantee uniqueness. Two unequal objects might have the same hash code, known as a hash collision.

In summary, hashCode() plays a crucial role in storing and retrieving objects quickly from large collections. It’s a fundamental part of the Java Collections Framework and Java’s data handling capabilities. 

The equals() method in Java is used to check if two objects are equal. This method is defined in the Object class, which is the superclass for all classes in Java. Here are some key points about the equals() method:

  1. Object Equality: The equals() method checks if two objects are equal in terms of their internal state, not their identities. In other words, it checks if two objects are logically equal.
  2. Default Behavior: The default implementation of equals() in the Object class checks for identity, meaning it returns true if two references point to the exact same object. However, many classes override this method to provide their own definition of equality.
  3. Contract with hashCode: There’s a contract between equals() and hashCode() that if two objects are equal according to the equals() method, then calling hashCode() on each of the two objects must return the same integer result. This is why when you override equals(), you should also override hashCode().
  4. Use in Collections: The equals() method is used by various classes in the Java Collections Framework, such as ArrayListHashSet, and HashMap, to check if a collection contains a certain element or to remove an element from the collection.

Here’s an example of how you might override the equals() method in a Person class:

Java
public class Person {
    private String name;
    private int age;

    // constructor, getters and setters...

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        Person person = (Person) obj;
        return age == person.age && name.equals(person.name);
    }
}

When storing objects in a collection, equals() and hashCode() play a vital role in the performance of retrieving the objects from the collection. If these methods are not implemented correctly, it can lead to incorrect results and inefficient performance.

For instance, in a HashMap, the hashCode() method is used to find the correct bucket location where the particular key-value pair resides, and the equals() method is used to prevent duplicate keys in the same bucket.

Contract between equals() and hashCode()

The contract between equals() and hashCode() is:

  1. 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.
  2. If two objects are unequal according to the equals(Object) method, it is not required that calling the hashCode method on each of the two objects must produce distinct integer results.

Conclusion

Understanding and correctly implementing equals() and hashCode() is crucial when creating objects that will be used in collections. They help ensure that our objects can be used reliably in complex data structures, leading to efficient Java applications.

I hope this blog post helps you understand the importance and usage of equals() and hashCode() in Java. Happy coding! 😊

Avatar

Neelabh

About Author

As Neelabh Singh, I am a Senior Software Engineer with 6.6 years of experience, specializing in Java technologies, Microservices, AWS, Algorithms, and Data Structures. I am also a technology blogger and an active participant in several online coding communities.

You may also like

Blog Design Pattern

Understanding the Builder Design Pattern in Java | Creational Design Patterns | CodeTechSummit

Overview The Builder design pattern is a creational pattern used to construct a complex object step by step. It separates
Blog Tech Toolkit

Base64 Decode

Base64 encoding is a technique used to encode binary data into ASCII characters, making it easier to transmit data over