Simple way to implement equals() & hashcode()
For any POJO classes with multiple attributes, generally equals & hashcode implementation is same in most of the cases. Mostly everyone follow guidelines given by author “Joshua Bloch”. So instead of writing code for equals & hashcode separately in each POJO class, apache provides easy & simple way to implement equals & hashcode methods as shown in below example.
In below example “Person” is a POJO class which needs equals() & hashcode() implementation. So we can use below builder classes provided by apache commons-lang API, which uses all attributes of “person” class to perform equality & to provide hashcode.
org.apache.commons.lang3.builder.EqualsBuilder.reflectionEquals()
org.apache.commons.lang3.builder.HashCodeBuilder.reflectionHashCode()
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 44 45 |
package ravi.tutorial.apache.lang3; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; public class EqualsHashcodeWithReflection { public static void main(String[] args) { Person tim = new Person("Tim", 30); Person tim_2 = new Person("Tim", 30); // Logically equal to tim. Person john = new Person("John", 35); // Equality check of 2 different & logical different object. System.out.println("tim.equals(john) = " + tim.equals(john)); // Equality of 2 different objects but logically equal. System.out.println("tim.equals(tim_2) = " + tim.equals(tim_2)); //Equality of same object to have consistent equals contract. System.out.println("john.equals(john) = " + john.equals(john)); } } /** * POJO class to implement equality; */ class Person{ private String name; private Integer age; public Person(String name, Integer age) { this.name = name; this.age = age; } @Override public boolean equals(Object obj) { // Apache lang3 org.apache.commons.lang3.builder.EqualsBuilder return EqualsBuilder.reflectionEquals(this, obj, true); } @Override public int hashCode() { // Apache lang3 org.apache.commons.lang3.builder.HashCodeBuilder return HashCodeBuilder.reflectionHashCode(this, true); } } |
Output:
1 2 3 |
tim.equals(john) = false tim.equals(tim_2) = true john.equals(john) = true |
You might want to exclude some attribute from equality or hashcode which can also be done very easily using simple annotations.
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 44 45 46 47 48 49 50 51 |
package ravi.tutorial.apache.lang3; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.EqualsExclude; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.HashCodeExclude; public class EqualsHashcodeWithExcludeFields { public static void main(String[] args) { EmployedPerson tim = new EmployedPerson("Tim", 20, "Fun IT"); EmployedPerson tim_newEmployer = new EmployedPerson("Tim", 20, "More Fun IT"); // Logically same tim but different employer. // Equality check of 2 different but logically same object. System.out.println("tim.equals(tim_newEmployer) = " + tim.equals(tim_newEmployer)); } } /** * POJO class to implement equality; */ class EmployedPerson{ private String name; private Integer age; /* * Since employer can keep changing, lets exclude employer from equality & hashcode. */ @EqualsExclude @HashCodeExclude private String employer; public EmployedPerson(String name, Integer age, String employer) { this.name = name; this.age = age; this.employer = employer; } @Override public boolean equals(Object obj) { // Apache lang3 org.apache.commons.lang3.builder.EqualsBuilder return EqualsBuilder.reflectionEquals(this, obj, true); } @Override public int hashCode() { // Apache lang3 org.apache.commons.lang3.builder.HashCodeBuilder return HashCodeBuilder.reflectionHashCode(this, true); } } |
Output:
1 |
tim.equals(tim_newEmployer) = true |