Thursday 9 July 2015

Usage of hashCode() and equals()

The hashCode() and equals() methods have been defined in Object class which is parent class for java objects. For this reason, all java objects inherit 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 used for determining the bucket location, when this object needs to be stored in some HashTable like data structure. By default, Object’s hashCode() method returns and integer representation of memory address where object is stored.
equals() method, as name suggest, is used to simply verify the equality of two objects. Default implementation simply check the object references of two objects to verify their equality.

Overriding the default behavior

Everything works fine until you do not override any of these methods in your classes. But, sometimes application needs to change the default behavior of some objects.
Lets take an example where your application has Employee object. 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 there accessor methods. Now consider a simple situation where you need to compare two employee 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));
    }
}
No prize for guessing. Above method will print “false“. But, is it really correct after knowing that both objects represent same employee. In a real time application, this must return true.

After override  equals() method in 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;
}


@Override

public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
if (department == null) {
if (other.department != null)
return false;
} else if (!department.equals(other.department))
return false;
if (firstname == null) {
if (other.firstname != null)
return false;
} else if (!firstname.equals(other.firstname))
return false;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (lastName == null) {
if (other.lastName != null)
return false;
} else if (!lastName.equals(other.lastName))
return false;
return true;
}
}


import java.util.HashSet;

import java.util.Set;

public class HashCodeAndEqualMethod {


private final String importantField;

private final String anotherField;

public HashCodeAndEqualMethod(final String equalField, final String anotherField) {

this.importantField = equalField;
this.anotherField = anotherField;
}

public String getEqualField() {

return importantField;
}

public String getAnotherField() {

return anotherField;
}

public static void main(String[] args) {

Employee e1 = new Employee();
Employee e2 = new Employee();

e1.setId(100);

e2.setId(100);

// Prints false in console if you are not override equals method in Employee class.

System.out.println(e1.equals(e2));

Set<Employee> employees = new HashSet<Employee>();

employees.add(e1);
employees.add(e2);

// Prints two objects if you are not override equals  and hashCode()  method in Employee class.

System.out.println(employees);
}

}



Output:


true

[Employee@10469e8, Employee@969cccc]


After override both hashCode() and equals() method in 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;
}

@Override

public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((department == null) ? 0 : department.hashCode());
result = prime * result + ((firstname == null) ? 0 : firstname.hashCode());
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((lastName == null) ? 0 : lastName.hashCode());
return result;
}

@Override

public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
if (department == null) {
if (other.department != null)
return false;
} else if (!department.equals(other.department))
return false;
if (firstname == null) {
if (other.firstname != null)
return false;
} else if (!firstname.equals(other.firstname))
return false;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (lastName == null) {
if (other.lastName != null)
return false;
} else if (!lastName.equals(other.lastName))
return false;
return true;
}
}


Output:

true
[Employee@e239d]



No comments:

Post a Comment