Override Equals, HashCode and CompareTo method in Java

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 hash code, which eventually helps to avoid collision, when used in hash based collections like Hash table and HashMap.

Sample implementation of 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 instance of 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 its better to use instance of 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 instance of if your class can be loaded by multiple class loader or it can be used by framework to create proxies.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/**
* Simple Java Class to represent Person with name, id and date of birth.
*/

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 boolean equals(Object other){
if(this == other) return true;

if(other == null || (this.getClass() != other.getClass())){
return false;
}

Person guest = (Person) other;
return (this.id == guest.id) &&
(this.name != null && name.equals(guest.name)) &&
(this.dob != null && dob.equals(guest.dob));
}

@Override
public int hashCode(){
int result = 0;
result = 31*result + id;
result = 31*result + (name !=null ? name.hashCode() : 0);
result = 31*result + (dob !=null ? dob.hashCode() : 0);

return result;
}

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

Sample JUnit test case for testing Equals and HashCode

Here is simplest of simple test case to verify equals and hashCode in Java. Remember this unit test is not enough, if you want to verify all properties of equals and hashCode. If you should write test cases to check if it verify key properties of equals and hashcode method e.g. if a equal b then b should also be equal to a, or if a a equals b and b equals c then a and c should also be equal to each other. You must also verify whether compareTo() return 0 for equal object and return non zero value for non equal objects.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.util.Date;
import org.junit.Test;
import static org.junit.Assert.*;

/**
* Simple example of using equals and hashCode method
*/

public class EqualsAndHashCodeTest {


@Test
public void testEquals(){
Person james = new Person("James", 21, new Date(1980,12, 1));
Person same = new Person("James", 21, new Date(1980,12, 1));
Person similar = new Person("Harry", 21, new Date(1981,12,1));

assertTrue(james.equals(same));
assertTrue(james.hashCode() == same.hashCode());

assertFalse(james.equals(null));

assertFalse(james.equals(similar));
assertTrue(james.hashCode() != similar.hashCode());
}

}
写得好!朕重重有赏!