http://howtodoinjava.com/2012/10/09/working-with-hashcode-and-equals-methods-in-java/
In this post, i will point out my understanding about hashCode() and equals() method. Iwill talk about their default implementation and how to correctly overridethem. I will also write about implement these methods using Apache Commonspackage’s utility classes.
Sections in this post:
- Usage of hashCode() and equals()
- Overriding the default behavior
- Overriding hashCode() and equals() using Apache Commons Lang
- Important things to remember
- Special Attention When Using in ORM
hashCode() and equals() methods have been defined in Object classwhich is parent class for java objects. For this reason, all java objectsinherit a default implementation of these methods.
Usage of hashCode() and equals()
hashCode()method is used to get a unique integer for given object. This integer is usedfor determining the bucket location, when this object needs to be stored insome HashTable like data structure. By default,Object’s hashCode() method returns and integer representation of memory addresswhere object is stored.
equals() method, as name suggest, is used to simply verify theequality of two objects. Default implementation simply check the objectreferences of two objects to verify their equality.
Overriding the default behavior
Everything works fine until you do not override any of thesemethods in your classes. But, sometimes application needs to change the defaultbehavior of some objects.
Letstake an example where your application has Employeeobject.Lets create a minimal possible structure of Employee class::
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;
}
}
Above Employee class has some very basic attributes and thereaccessor methods. Now consider a simple situation where you need to compare twoemployee objects.
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));
}
}
Noprize for guessing. Above method will print “false“. But, is it really correct after knowingthat both objects represent same employee. In a real time application, thismust return true.
To achieve correct behavior, we need to override equals method asbelow:
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());
}
Addthis method to your Employee class, and EqualsTest will start returning “true“.
So are we done? Not yet. Lets test again above modified Employeeclass in different way.
public class EqualsTest {
public static void main(String[] args) {
Employee e1 = new Employee();
Employee e2 = new Employee();
Employee e3 = new Employee();
e1.setId(100);
e2.setId(100);
e3.setId(200);
//Prints false in console
System.out.println(e1.equals(e2));
Set<Employee> employees = new HashSet<Employee>();
employees.add(e1);//call hashcode
employees.add(e2);//call hashcode, then call equals(because there is a conflict)
employees.add(e3);//call hashcode
//Prints two objects
System.out.println(employees);
}
Above class prints two objects in second print statement. If bothemployee objects have been equal, in a Set which stores only unique objects,there must be only one instance inside HashSet, after all both objects refer tosame employee. What is it we are missing??
We aremissing the second important method hashCode(). As java docs say, if youoverride equals() method then you mustoverridehashCode() method. So lets 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 above method is added in Employee class, the second statementstart printing only single object in second statement, and thus validating thetrue equality of e1 and e2.
Overriding hashCode() and equals() usingApache Commons Lang
Apache commons provide two excellent utility classes forgenerating hash code and equals methods. Below is its usage:
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();
}
}
Alternatively, ifyou are using any code editor, they also must be capable of generating somegood structure for you. For example, Eclipse IDE has option under right click on class >> source > Generate hashCode() andequals() … willgenerate a very good implementation for you.
Important things to remember
1) Always use same attributes of an object to generate hashCode()and equals() both. As in our case, we have used employee id.
2)equals() must be consistent (if the objects are not modified, then itmust keep returning the same value).
3)Whenever a.equals(b), then a.hashCode() must besame asb.hashCode().
4) If you override one, then you should override the other.