Equals and hashcode methods are two primary but yet one of most important methods for java developers to be aware of. Java intends to provide equals and hashcode for every class to test the equality and to provide a hash or digest based on content of class. Importance of hashcode increases when we use the object in different collection classes which works on hashing principle e.g. hashtable and hashmap. A well written hashcode method can improve performance drastically by distributing objects uniformly and avoiding collision.
General Contracts for hashCode() in Java
1) If two objects are equal by equals() method then there hashcode returned by hashCode() method must be same.
2) Whenever hashCode() mehtod is invoked on the same object more than once within single execution of application, hashCode() must return same integer provided no information or fields used in equals and hashcode is modified. This integer is not required to be same during multiple execution of application though.
3) If two objects are not equals by equals() method it is not require that there hashcode must be different. Though it’s always good practice to return different hashCode for unequal object. Different hashCode for distinct object can improve performance of hashmap or hashtable by reducing collision.
Overriding hashCode method in Java
We will follow step by step approach for overriding hashCode method. This will enable us to understand the concept and process better.
1) Take a prime hash e.g. 5, 7, 17 or 31 (prime number as hash, results in distinct hashcode for distinct object)
2) Take another prime as multiplier different than hash is good.
3) Compute hashcode for each member and add them into final hash. Repeat this for all members which participated in equals.
4) Return hash
Here is an example of hashCode() method
@Override
public int hashCode() {
int hash = 5;
hash = 89 hash + (this.name != null ? this.name.hashCode() : 0);
hash = 89 hash + (int) (this.id ^ (this.id >>> 32));
hash = 89 hash + this.age;
return hash;
}
It’s always good to check null before calling hashCode() method on members or fields to avoid NullPointerException, if member is null than return zero. Different data types has different way to compute hashCode.Integer members are simplest we just add there value into hash, for other numeric data-type are converted into int and then added into hash. Joshua bloach has full tables on this. I mostly relied on IDE for this.equals() method
This method returns a boolean which specifies whether two objects are equal or not. The default implementation of equals() method given by the Object Class uses the ‘==’ operator to compare two object references, and returns true only if they refer to the same object. But, we can meaningfully re-define this equals() method to have en equality check based on our own criteria.
Consider the following code, which defines two user defined classes Employee and EmployeeId which are supposed to be stored in a Map.
public class Employee {
private String name;
public Employee(String name) {
this.name = name;
}
public String toString() {
return name;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj.getClass() != getClass()) {
return false;
}
Employee emp = (Employee) obj;
if (this.name == emp.name) {
return true;
}
return false;
}
@Override
public int hashCode() {
return name.hashCode();
}
} public class EmployeeId {
private String id;
public EmployeeId(String id) {
this.id = id;
}
public String toString() {
return id;
}
public boolean equals(Object obj) {
if (obj == null)
return false;
if (obj.getClass() != getClass()) {
return false;
}
EmployeeId empId = (EmployeeId) obj;
if (this.id == empId.id) {
return true;
}
return false;
}
@Override
public int hashCode() {
return id.hashCode();
}
} EqualsBuilder and HashCodeBuilder from Apache commons are much better way to override equals and hashcode method, at least much better than ugly equals, hashcode generated by Eclipse.