hashCode and equals methods in Java

hashCode and equals Methods Override

hashCode() and equals() methods have been defined in Object class which is parent class for java objects.So every java object has access to the equals() method. If you override the equals(), you must override hashCode() Otherwise its a violation of the general contract for Object equality.

Use of hashCode() and equals() method

hashcode():

hashCode() method is used to get a unique integer for given object.By default, Object’s hashCode() method returns and integer representation of memory address where object is stored. This integer is used for determining the bucket location, when this object needs to be stored in some HashTable like data structure.

equals():

This method is used to simply check the equality between two objects. By default, it checks where two reference refer to same object or not.

hashCode and equals Methods Override

hashCode() and equals() methods have been defined in Object class which is parent class for java objects.So every java object has access to the equals() method. If you override the equals(), you must override hashCode() Otherwise its a violation of the general contract for Object equality.

Use of hashCode() and equals() method

hashcode():

hashCode() method is used to get a unique integer for given object.By default, Object’s hashCode() method returns and integer representation of memory address where object is stored. This integer is used for determining the bucket location, when this object needs to be stored in some HashTable like data structure.

equals():

This method is used to simply check the equality between two objects. By default, it checks where two reference refer to same object or not.



Overriding equals() and hashcode() method

Sometimes in Real Time application default behavior needs to be changed for some objects.Lets see with the help of example.We have a class called Customer

Customer.java

package com.jwt.java;

public class Customer {
	private Integer id;
	private String firstname;
	private String lastName;
	private String city;

	/**
	 * @return the id
	 */
	public Integer getId() {
		return id;
	}

	/**
	 * @param id
	 *            the id to set
	 */
	public void setId(Integer id) {
		this.id = id;
	}

	/**
	 * @return the firstname
	 */
	public String getFirstname() {
		return firstname;
	}

	/**
	 * @param firstname
	 *            the firstname to set
	 */
	public void setFirstname(String firstname) {
		this.firstname = firstname;
	}

	/**
	 * @return the lastName
	 */
	public String getLastName() {
		return lastName;
	}

	/**
	 * @param lastName
	 *            the lastName to set
	 */
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	/**
	 * @return the city
	 */
	public String getCity() {
		return city;
	}

	/**
	 * @param city
	 *            the city to set
	 */
	public void setCity(String city) {
		this.city = city;
	}

}

In the above Customer class there are five attributes id,firstName,lastName and city.Now create a class called EqualityTest.java to test the object equality.

EqualityTest.java

package com.jwt.java;

public class EqualityTest {

	public static void main(String as[]) {
		Customer customer1 = new Customer();
		Customer customer2 = new Customer();
		customer1.setId(101);
		customer2.setId(101);
		System.out.println(customer1.equals(customer2));
	}
}

When you run above program, you will get following output.

Output

false

In above program, we have created two different objects and set their id to 101.Because both references customer1 and customer2 are pointing to different object, as the default implementation of equals method is returning false. In real life, it should return true because no two customer can have same id.

To achieve correct behaviour, we need to override equals method as given below:

public boolean equals(Object obj) {
		if (!(obj instanceof Customer))
			return false;
		if (obj == this)
			return true;
		return this.id.equals(((Customer) obj).id);
	}

Add this method to your Customer class, and now EqualityTest will start returning “true“.This is because in overriden equals method is returning true if two Customer have same id.

Lets put this Customer objects as key in HashMap.

package com.jwt.java;

import java.util.HashMap;
import java.util.Map;

public class HashMapEqualityTest {

	public static void main(String as[]) {

		Map<Customer, String> hmap = new HashMap<Customer, String>();
		Customer customer1 = new Customer();
		Customer customer2 = new Customer();
		customer1.setId(101);
		customer2.setId(101);
		hmap.put(customer1, "Ravi");
		hmap.put(customer2, "Ravi");
		for (Map.Entry me : hmap.entrySet()) {
			System.out.println("Customer Name is " + me.getValue());

		}
	}

}

When you run above program, you will see following output:

Output

Customer Name is Ravi
Customer Name is Ravi

In the above program both objects are equal but HashMap contains two key value pair instead of one.This is because First HashMap uses hashcode() to find bucket for that key object, if hashcode() are same then only it checks for equals method and because hashcode() for above two Customer objects uses default hashcode method,Both will have different memory address hence different hashcode.

In the Customer class we didn't overrided important method hashCode(). As java docs say, if you override equals() method then you must override hashCode() method. So lets add another method hashCode() in our Customer class.

public int hashCode() {
		int val = 3;
		int result = (int) (id / val);
		return result;
	}

Now run HashMapEqualityTest.java again You will see following output:

Output

Customer Name is Ravi

Now hashcode for above two objects cutomer1 and customer2 are same, so Both will be point to same bucket,now equals method will be used to compare them which will return true.This is the reason why java doc says "if you override equals() method then you must override hashCode() method".

Final code for Customer.java is given below.

package com.jwt.java;

public class Customer {
	private Integer id;
	private String firstname;
	private String lastName;
	private String city;

	/**
	 * @return the id
	 */
	public Integer getId() {
		return id;
	}

	/**
	 * @param id
	 *            the id to set
	 */
	public void setId(Integer id) {
		this.id = id;
	}

	/**
	 * @return the firstname
	 */
	public String getFirstname() {
		return firstname;
	}

	/**
	 * @param firstname
	 *            the firstname to set
	 */
	public void setFirstname(String firstname) {
		this.firstname = firstname;
	}

	/**
	 * @return the lastName
	 */
	public String getLastName() {
		return lastName;
	}

	/**
	 * @param lastName
	 *            the lastName to set
	 */
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	/**
	 * @return the city
	 */
	public String getCity() {
		return city;
	}

	/**
	 * @param city
	 *            the city to set
	 */
	public void setCity(String city) {
		this.city = city;
	}

	public boolean equals(Object obj) {
		if (!(obj instanceof Customer))
			return false;
		if (obj == this)
			return true;
		return this.id.equals(((Customer) obj).id);
	}

	public int hashCode() {
		int val = 3;
		int result = (int) (id / val);
		return result;
	}
}


hashcode() and equals() contracts:

equals Method

  • equals() method is used to determine the equality of two objects. When we say equality, it should adhere by the following properties.
  • Reflexive: Always, a = a. In Java, a.equals(a) should always be true.
  • Symmetric: If a = b, then b = a. In Java, if a.equals(b) is true, then b.equals(a) should be true.
  • Transitive: If a = b and b = c, then a = c. In Java, if a.equals(b) and b.equals(c) is true, then a.equals(c) should be true.

hashcode():

  • Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. 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(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
  • It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

Steps that need to be taken into consideration while implementing equals method.

  • Use the == operator to check if the argument is a reference to this object. If so, return true. This is just a performance optimization, but one that is worth doing if the comparison is potentially expensive.
  • Use the instanceof operator to check if the argument has the correct type.
  • Cast the argument to the correct type. Because this cast was preceded by an instanceof test, it is guaranteed to succeed.
  • For each significant field in the class, checks if that field of the argument matches the corresponding field of this object.If all these tests succeed, return true; otherwise, return false.

Next Topic :-Java Exception Handling Keywords




comments powered by Disqus