Overriding Equals, HashCode and CompareTo in Java

In this Java program, we will override all three method for a Person class, which contains a String name, an integer id and a Date for date of birth. In order to override equals, you need to follow certain checks, e.g. checking null, checking type of object etc, Also your equals() method, when compared with null, should return false instead of throwing NullPointerException. See this post for detailed tips on overriding equals method in Java. For overriding hashCode, you need to choose a prime, usually 31, but you can also choose other prime numbers e.g. 37, 17 etc. The reason for choosing these prime numbers are to generate a uniquely distributed hashcode, which eventually helps to avoid collision, when used in hash based collections like Hashtable and HashMap. Another worth noting thing is using all variables, used in equals, in hashCode method to keep equals and hashCode consistent, and adhere to rules of overriding hashCode in Java. I have already discussed about Comparable and compareTo method, while sorting list of objects in Java. A simple implementation of compareTo must return negative number if current object is lesser than provided object, positive if current object is greater in order than provided and zero if both objects are equal. Another worth noting point is that, compareTo() and equals() must be consistent with each other, otherwise your object will not behave properly on Collection classes, which uses compareTo() for sorting e.g. TreeSet or TreeMap. Anyway, here is a simple example of overriding equals, hashcode and compareTo in Java.

In this sample example of overriding equals, hashcode and compareTo method, we will use a class named Person which has 3 properties String name, int id and Date to represent date of birth.  We will also use Generics along with Comparable to provide a type safe implementation. Remember we have used getClass() method instead of instanceof operator, which means a Person class cannot be equal to its subclass, this could create problem if you are using this class in EJB or any application server, where there is a chance that same class is loaded by two separate class loader. On those cases it's better to use instanceof operator because it will allow a Class to be equal to its subclass if rest of properties matched. This is also true for framework like Hibernate, which provides proxy implementation, which is essentially sub class of entity classes. In short, use instanceof if your class can be loaded by multiple class loader or it can be used by framework to create proxies.

import java.util.Date;

/**
 * Simple Person class to represent name, id and dob of a person
 * @author Arun.Singh
 *
 */
public class Person implements Comparable<Person> {
private String name;
private int id;
private Date dob;

public Person(String name, int id, Date dob) {
this.name = name;
this.id = id;
this.dob = dob;
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((dob == null) ? 0 : dob.hashCode());
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.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;
Person other = (Person) obj;
if (dob == null) {
if (other.dob != null)
return false;
} else if (!dob.equals(other.dob))
return false;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}

@Override
public int compareTo(Person o) {
return this.id - o.id;
}

}

Share on Google Plus

About Admin

Arun is a JAVA/J2EE developer and passionate about coding and managing technical team.
    Blogger Comment
    Facebook Comment

0 comments:

Post a Comment