In this article, I will tell you my understanding of hashCode and equals methods. I'll discuss their default implementations and how to override them correctly. I will also make an implementation using the toolkit provided by Apache Commons.
Table of contents:
Usage of hashCode() and equals()
Override the default implementation
Use the Apache Commons Lang package to rewrite hashCode() and equals()
Things to remember
When using When using ORM, you should pay special attention to
hashCode() and equals() are defined in the Object class. This class is the base class of all java classes, so all java classes inherit these two methods.
Using hashCode() and equals()
hashCode() method is used to get the unique integer of a given object. This integer is used to determine where the object is stored in a HashTable-like structure. By default, the hashCode() method of the Object class returns the number of the memory address where this object is stored.
Override the default implementation
If you do not override these two methods, you will hardly encounter any problems, but sometimes the program requires us to change the default implementation of some objects.
Let's take a look at this example, let's create a simple class Employee
public class Employee { private Integer id; private String firstname; private String lastName; private String department; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getDepartment() { return department; } public void setDepartment(String department) { this.department = department; } }
The above Employee class just has some very basic properties and getters and setters. Now consider a situation where you need to compare two employees.
public class EqualsTest { public static void main(String[] args) { Employee e1 = new Employee(); Employee e2 = new Employee(); e1.setId(100); e2.setId(100); //Prints false in console System.out.println(e1.equals(e2)); } }
There is no doubt that the above program will output false, but in fact the above two objects represent an employee. Real business logic wants us to return true.
In order to achieve this purpose, we need to override the equals method.
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 in the above class, EauqlsTest will output true.
So are we done? No, let’s change the testing method to see.
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); //Prints two objects System.out.println(employees); }
The output results of the above program are two. If equals of two employee objects returns true, only one object should be stored in Set. What is the problem?
We forgot the second important method hashCode(). As stated in the JDK Javadoc, if you override the equals() method, you must override the hashCode() method. If we add the following method, the program will execute correctly.
@Override public int hashCode() { final int PRIME = 31; int result = 1; result = PRIME * result + getId(); return result; }
Use the Apache Commons Lang package to rewrite the hashCode() and equals() methods
The Apache Commons package provides two excellent classes to generate the hashCode() and equals() methods. See the program below.
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; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getDepartment() { return department; } public void setDepartment(String department) { this.department = department; } @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(); } }
If you use Eclipse or other IDE, the IDE may also provide well-generated hashCode() method and equals() method.
Things to remember
Try to ensure that the same property of the object is used to generate hashCode() and equals() methods. In our case, we use employee id.
The eqauls method must be consistent (if the object has not been modified, equals should return the same value)
Any time a.equals(b) is used, then a.hashCode() must be equal to b.hashCode().
Both must be rewritten at the same time.
Pay special attention when using ORM
If you use ORM to process some objects, you have to make sure to use getters and setters in hashCode() and equals() objects instead of directly referencing member variables. Because sometimes member variables in ORM are loaded lazily, these variables are only really available when the getter method is called.
For example, in our example, this problem may occur if we use e1.id == e2.id, but this problem will not occur if we use e1.getId() == e2.getId().
For more articles related to the correct use of hashCode and equals methods in Java, please pay attention to the PHP Chinese website!