A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://howtodoinjava.com/java/basics/java-hashcode-equals-methods/ below:

Java hashCode() and equals() Methods

Learn about Java hashCode() and equals() methods, their default implementation, and how to correctly override them. Also, we will learn to implement these methods using 3rd party classes HashCodeBuilder and EqualsBuilder.

The hashCode() and equals() methods have been defined in Object class which is parent class for all java classes. For this reason, all java objects inherit a default implementation of these methods.

1. The hashCode() and equals() Methods 1.1. Contract between hashCode() and equals()

Overriding the the hashCode() is generally necessary whenever equals() is overridden to maintain the general contract for the hashCode() method, which states that equal objects must have equal hash codes.

2. Overriding the Default Behavior

Everything works fine until we do not override any of both methods in our classes. But, sometimes, the application needs to change the default behavior of some objects.

Let us understand why we need to override equals and hashcode methods.

2.1. The Default Behavior

Let’s take an example where your application has Employee object. Let us create a minimal possible structure of Employee class:

public class Employee
{
	private Integer id;
	private String firstname;
	private String lastName;
	private String department;

	//Setters and Getters
}

Above Employee class has some fundamental attributes and their accessor methods. Now consider a simple situation where you need to compare two Employee objects. Both employee objects have the same id.

public class EqualsTest {
	public static void main(String[] args) {
		Employee e1 = new Employee();
		Employee e2 = new Employee();

		e1.setId(100);
		e2.setId(100);

		System.out.println(e1.equals(e2));	//false
	}
}

No prize for guessing. The above method will print “false.”

But is it correct after knowing that both objects represent the same employee? In a real-time application, this should return true.

2.2. Overriding only equals()

To achieve correct application behavior, we need to override equals() method as below:

public boolean equals(Object o) {
	if(o == null)
	{
		return false;
	}
	if (o == this)
	{
		return true;
	}
	if (getClass() != o.getClass())
	{
		return false;
	}

	Employee e = (Employee) o;
	return (this.getId() == e.getId());
}

Add this method to the Employee class, and EqualsTest will start returning "true".

So are we done? Not yet. Let’s test the above-modified Employee class again in a different way.

import java.util.HashSet;
import java.util.Set;

public class EqualsTest
{
	public static void main(String[] args)
	{
		Employee e1 = new Employee();
		Employee e2 = new Employee();

		e1.setId(100);
		e2.setId(100);

		//Prints 'true'
		System.out.println(e1.equals(e2));

		Set<Employee> employees = new HashSet<Employee>();
		employees.add(e1);
		employees.add(e2);

		System.out.println(employees);	//Prints two objects
	}
}

The above example prints two objects in the second print statement.

If both employee objects have been equal, in a Set which stores unique objects, there must be only one instance inside HashSet because both objects refer to the same employee. What is it we are missing??

2.3. Overriding hashCode() is Also Necessary

We are missing the second important method hashCode(). As java docs say, if we override equals() then we must override hashCode(). So let’s add another method in our Employee class.

@Override
public int hashCode()
{
	final int PRIME = 31;
	int result = 1;
	result = PRIME * result + getId();
	return result;
}

Once the above method is added in Employee class, the second statement starts printing only a single object in the second statement and thus validating the true equality of e1 and e2.

3. EqualsBuilder and HashCodeBuilder

Apache commons provide two excellent utility classes HashCodeBuilder and EqualsBuilder for generating hash code and equals methods.

We can use these classes in the following manner.

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
public class Employee
{
	private Integer id;
	private String firstname;
	private String lastName;
	private String department;

	//Setters and Getters

	@Override
	public int hashCode()
	{
		final int PRIME = 31;
		return new HashCodeBuilder(getId()%2==0?getId()+1:getId(), PRIME).toHashCode();
	}

	@Override
	public boolean equals(Object o) {
	if (o == null)
	   return false;

	if (o == this)
	   return true;

	if (o.getClass() != getClass())
	   return false;

	Employee e = (Employee) o;

	return new EqualsBuilder().
			  append(getId(), e.getId()).
			  isEquals();
	}
}
4. Generating hashCode() and equals() in Eclipse IDE

Most editors provide common source code templates. For example, Eclipse IDE has the option to generate an excellent implementation of hashCode() and equals().

Right click on Java file -> Source -> Generate hashCode() and equals() …

Generate hashCode() and equals() In Eclipse 5. Best Practices to Follow
  1. Always use the same fields to generate hashCode() and equals(). As in our case, we have used employee id.
  2. The equals() must be consistent (if the objects are not modified, then it must keep returning the same value).
  3. Whenever a.equals(b), then a.hashCode() must be same as b.hashCode().
  4. If we override one method, then we should override the other method as well.
6. Special Attention When Declared in an JPA Entity

If you’re dealing with an ORM, make sure always to use getters and never use the field references in hashCode() and equals(). Because in ORM, occasionally fields are lazy loaded and not available until we call their getter methods.

For example, In our Employee class if we use e1.id == e2.id. It is very much possible that id field is lazy-loaded. So, in this case, id field inside the methods might be zero or null, and thus resulting in incorrect behavior.

But if uses e1.getId() == e2.getId(), we can be sure even if the field is lazy-loaded, calling the field getter will populate the field first.

Happy Learning !!


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4