equals and hashcode in java – When to use?

equals and hashcode method:

equals() and hashcode() are two important methods defined in java.lang.Object class. These methods form the base to compare objects for equality, primarily inside hash based collections such as Hashtable and HashMap. In this article I will explain you my understanding on these methods and when it becomes necessary to override these methods.

equals()

This particular method is used to compare the calling the object (this) with another object. Below is the definition of equals() method inside the Object class.

public boolean equals(Object obj)
{
return (this == obj);
}

The equals method implements an equivalence relation on non-null object references. The default implementation of this method in Object class simply checks if two object references x and y refer to the same memory address i.e. checks if x == y. Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general agreement for the hashCode method, which states that equal objects must have equal hash codes.

hashCode()

Returns a hash code value for the object. This method returns the hash code value as an integer and is supported for the benefit of hash based collections such as Hashtable, HashMap etc. The default implementation of hashCode() provided by Object is derived by mapping the memory address to an integer value. Below is the syntax of the method defined in Object class.

public native int hashCode();

It indicates that hashCode is the native implementation which provides the memory address to a certain extent. It is important that this method is overridden in every class that overrides the equals method. Failing to comply with this requirement usually results in undetermined, undesired behaviour of the class when confronted with Java collection classes or any other Java classes.

General agreement between equals and hashcode method

  • The integer returned by the hashCode method must be the same for multiple invocations during the same execution of a Java application as long as the object is not modified which affects the equals comparison. This integer need not remain consistent from one execution of an application to another execution of the same application.
  • If two objects are equal according to the equals() method, then calling the hashCode method on each of the two objects must produce the same integer result i.e. equal objects must produce the same hash code.
  • It is not required that if two objects are unequal according to the equals() method, then calling the hashCode method on each of the two objects must produce distinct integer results i.e. unequal objects need not produce distinct hash codes. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

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.

Override Example:

Below is the output of running the above program.

Equals Comparison: emp1 and emp2 are equal – true

emp1 hashcode: 107310

emp2 hashcode: 107310

Let us examine both the methods.

The equals method is implemented such that, it returns true if and only if both id and name of the objects are equal.

Next the hashcode method uses both the variables id and name for calculating the hash code value. This implementation ensures that the general agreement of the hashCode method is not violated. This implementation will return consistent hash code values for different invocations and will also ensure that equal objects will have equal hash codes.

Some tips for hashcode implementation:

  • Store an arbitrary non-zero constant integer value (say 7) in an int variable, called hash.
  • Involve significant variables of your object in the calculation of the hash code, all the variables that are part of equals comparison should be considered for this.
  • Review your hashCode method and check if it is returning equal hash codes for equal objects. Also, verify that the hash codes returned for the object are consistently the same for multiple invocations during the same execution.

Now let us see why it is important to override hashcode() when equals() is overridden and vice versa.

Consider the below example,

Running the above program will produce the below result,

Employee set size – 1

You should remember that the HashSet is a collection that contains no duplicate elements. This contract would have been violated if the hashcode method is not overridden. Remove the hashcode method in the above program and run, you will get the output as “Employee set size – 2”.

This is because two things happens when the add() method is invoked on the HashSet reference.

  1. First the hashcode of the object being added is calculated. Then the hash bucket with the hashcode calculated is identified.
  2. Next the object being added is compared with every other object in the hash bucket identified earlier. This comparison is done with the help of equals method.

(To understand how the hashing principle works, read this article, Hash table. In simple terms, hashing is implemented with the help of a 2-D array).

In the above example program, let us see what will happen if hashcode() method is not overridden.

In the first add() statement, hashcode of emp1 will be calculated and hash bucket is referred and since there is no other object exists, emp1 is added to the hashset. Then in the second add() statement, hashcode of emp2 will be calculated. Now since hashcode() method is not overridden, the hashcode calculated in the second statement differs from the one calculated in the first statement. So now a different hash bucket is referred and equals method is invoked to see if similar object exits. Since there is no other object in the bucket, emp2 is also added to the hashset. Hence the size of hashset is returned as 2. Hence the contract of hashset is violated here.

Similar case can be proved in the above program by removing equals method and overriding hashcode() alone.

Summary

  • The default implementation of equals method compares memory address.
  • Equal objects must produce the same hash code as long as they are equal, however unequal objects need not produce distinct hash codes.
  • The equals method only takes Java objects as an argument, and not primitives; passing primitives will result in a compile time error.
  • The String class overrides the equals method to check if two string objects contains same character sequence.
  • The class java.lang.StringBuffer does not override the equals method, and hence it inherits the implementation from java.lang.Object class.
  • If null is passed as an argument to the equals method, it will return false.
  • Equal hash codes do not imply that the objects are equal.
  • return 1; is a legal implementation of the hashCode method, however it is a very bad implementation. It is legal because it ensures that equal objects will have equal hash codes, it also ensures that the hash code returned will be consistent for multiple invocations during the same execution. Thus, it does not violate the general contract of the hashCode method. It is a bad implementation because it returns same hash code for all the objects. This explanation applies to all implementations of the hashCode method which return same constant integer value for all the objects.
  • It is incorrect to involve a random number directly while computing the hash code of the class object, as it would not consistently return the same hash code for multiple invocations during the same execution.
  • Equal objects must produce the same hash code.
  • It is important to override hashcode method when equals() method is overridden and vice versa.

Some of the Java interview questions in equals() and hashcode()

  • What is hash code?
  • What is the contract between hashcode() and equals() method.
  • Difference between equals () and hashCode() method and when do you override it and explain the practical use of overriding it.
  • Can two object which are not equal have same hashCode? Yes
  • How does get() method of HashMap works? (It is similar to the steps for add() method explained earlier).
  • What is difference between “==” and equals() method in Java?
  • What happens when hashcode() is not overridden but equals was overridden?

If you find any error in the post, please leave a comment. I will update it.

Happy Learning!!

The following two tabs change content below.
Working as a Java developer since 2010. Passionate about programming in Java. I am a part time blogger.
2 comments
  1. Your topic has a lot of errors………………though your understanding is correct, you are confusing the reader by putting a lot of error statements like this one

    ……….Since hashcode() method is not overridden,……….

    Please correct the typo.

    • Hi Brindha,
      Thanks for pointing it out. The sentence is correct but the context was missing. It has been corrected. Now read it.
      What are the other errors you see?

Add Comment

Required fields are marked *. Your email address will not be published.