hashcode and equals method are declared in the Object class in Java. Since Object class is inherited by all classes, these two methods are inherited by all classes in Java. Though equals method is used for object comparison but both these methods become significant in collection classes like HashMap, Hashtable, HashSet and LinkedHashMap. The above mentioned collection classes make use of hashcode for storing elements in the memory.

Importance of hashcode

The use of hashcode results in better time complexity and improved performance for hashcode based collections. There is a contract defined by JDK which should be followed between the hashcode and equals method. If the contract is not followed then the storage and retrieval of objects from collection is not as expected. I am concentrating on the hashcode and equals contract here, but you may want to understand hashcode method in detail.

Let us first have a look at the contract between hashcode and equals method and then see code examples which demonstrate how things can go wrong if the contract is not followed:

The contract says:

  • If the equals method returns true for two objects then the hashcode of those two objects should be same.
  • However, if the hashcode of two objects is same then it is not necessary for them to be equal as per equals method.

The important point to note about the above text is that it is not must to have same hashcode for equal objects. Thus the contract can be violated but that can result in unexpected behavior as shown in following code:

To understand the program, you need to know that the hashcode method is invoked for put and get operations of HashMap. The use of hashcode provides O(1) time complexity for storage and retrieval operations.

Random hashcode breaking the contract

package com.example;

import java.util.HashMap;
import java.util.Random;


public class Test {

    int a;

    public static void main(String args[]) {
        Test t1 = new Test();
        t1.a = 10;
        Test t2 = new Test();
        t2.a = 12;
        Test t3 = new Test();
        t3.a = 14;

        HashMap<Test, String> m = new HashMap<Test, String>();
        m.put(t1, "a");
        m.put(t2, "b");

        System.out.println(m.get(t1));
        System.out.println(m.get(t2));
    }

    @Override
    public int hashCode() {
        Random rand = new Random();
        return rand.nextInt();
    }

    @Override
    public boolean equals(Object obj) {
        Test t = (Test) obj;
        if(this.a==t.a) {
            return true;
        } else {
            return false;
        }
    }
}

The above program generates a random integer for each invocation of hashcode method which is a clear violation of the hashcode and equals contract. The program compiles fine and runs without any exception. The problem is that since hashcode is different for each invocation for the same object, the key object can’t be looked up in the hash bucket when performing the get operation. A sample run of the above program produces the following output:

null
null

Note that the code could give correct output for get method of HashMap when the same random number is generated as during the put operation of HashMap.

Constant hashcode

If we modify the hashcode method in above program as following:

    @Override
    public int hashCode() {
        return 1;
    }

Since the above implementation is always returning the same hashcode for all objects, it is inefficient but still is not breaking the first point of the contract. Two equal objects are having the same hashcode in this case. The above program will always return correct results even if we add more objects to the hashmap.

Related Posts

Hashcode and equals contract admin Core Java
hashcode and equals method are declared in the Object class in Java. Since Object class is inherited by all classes, these two methods are inherited by all classes in Java. Though equals method is used for object comparison but both these methods become significant in collection classes like HashMap,...
hashcode and equals method are declared in the Object class in Java. Since Object class is inherited by all classes, these two methods are inherited by all classes in Java. Though equals method is used for object comparison but both these methods become significant in collection classes like <a href="http://www.javaexperience.com/differences-between-hashmap-and-hashtable-in-java/">HashMap, Hashtable</a>, HashSet and LinkedHashMap. The above mentioned collection classes make use of hashcode for storing elements in the memory. <h2>Importance of hashcode</h2> The use of hashcode results in better time complexity and improved performance for hashcode based collections. There is a contract defined by JDK which should be followed between the hashcode and equals method. If the contract is not followed then the storage and retrieval of objects from collection is not as expected. I am concentrating on the hashcode and equals contract here, but you may want to <a href="http://www.javaexperience.com/java-dive-deep-into-hashcode-internals/">understand hashcode method in detail</a>. Let us first have a look at the contract between hashcode and equals method and then see code examples which demonstrate how things can go wrong if the contract is not followed: <strong>The contract says:</strong> <ul> <li>If the equals method returns true for two objects then the hashcode of those two objects should be same.</li> <li>However, if the hashcode of two objects is same then it is not necessary for them to be equal as per equals method.</li> </ul> The important point to note about the above text is that it is not must to have same hashcode for equal objects. Thus <strong>the contract can be violated but that can result in unexpected behavior</strong> as shown in following code: To understand the program, you need to know that the hashcode method is invoked for put and get operations of HashMap. The use of <a href="http://www.javaexperience.com/time-complexity-of-collection-classes/">hashcode provides O(1) time complexity</a> for storage and retrieval operations. <h2>Random hashcode breaking the contract</h2> 1 The above program generates a random integer for each invocation of hashcode method which is a clear violation of the hashcode and equals contract. The program compiles fine and runs without any exception. The problem is that since hashcode is different for each invocation for the same object, the key object can't be looked up in the hash bucket when performing the get operation. A sample run of the above program produces the following output: <blockquote>null null</blockquote> Note that the code could give correct output for get method of HashMap when the same random number is generated as during the put operation of HashMap. <h2>Constant hashcode</h2> If we modify the hashcode method in above program as following: 1 Since the above implementation is always returning the same hashcode for all objects, it is inefficient but still is not breaking the first point of the contract. Two equal objects are having the same hashcode in this case. The above program will always return correct results even if we add more objects to the hashmap.
Java collection interview questions
Time complexity of collection classes
The following two tabs change content below.
I run this blog with lots of passion. In this website, you will find tutorials on Core Java, Spring, Struts, Web Applications, Portals and Database. Please support me and the website by sharing the posts on your facebook / twitter. You can tap the share button at the top of each post. Thanks for the support.

Latest posts by admin (see all)

Comments

comments