Java – How to override equals and hashCode
Some Java examples to show you how to override equals
and hashCode
.
1. POJO
To compare two Java objects, we need to override both equals
and hashCode
(Good practice).
User.java
public class User {
private String name;
private int age;
private String passport;
//getters and setters, constructor
}
User user1 = new User("mkyong", 35, "111222333");
User user2 = new User("mkyong", 35, "111222333");
System.out.println(user1.equals(user2)); // false
2. Classic Way
The 17 and 31 hash code idea is from the classic Java book – effective Java : item 9
User.java
public class User {
private String name;
private int age;
private String passport;
//getters and setters, constructor
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof User)) {
return false;
}
User user = (User) o;
return user.name.equals(name) &&
user.age == age &&
user.passport.equals(passport);
}
//Idea from effective Java : Item 9
@Override
public int hashCode() {
int result = 17;
result = 31 * result + name.hashCode();
result = 31 * result + age;
result = 31 * result + passport.hashCode();
return result;
}
}
2. JDK 7
For JDK 7 and above, you can use the new Objects
class to generate the equals and hash code values.
User.java
import java.util.Objects;
public class User {
private String name;
private int age;
private String passport;
//getters and setters, constructor
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof User)) {
return false;
}
User user = (User) o;
return age == user.age &&
Objects.equals(name, user.name) &&
Objects.equals(passport, user.passport);
}
@Override
public int hashCode() {
return Objects.hash(name, age, passport);
}
}
3. Apache Commons Lang
Alternatively, you can use the Apache Commons Lang EqualsBuilder
and HashCodeBuilder
function.
User.java
import org.apache.commons.lang3.builder;
public class User {
private String name;
private int age;
private String passport;
//getters and setters, constructor
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof User)) {
return false;
}
User user = (User) o;
return new EqualsBuilder()
.append(age, user.age)
.append(name, user.name)
.append(passport, user.passport)
.isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder(17, 37)
.append(name)
.append(age)
.append(passport)
.toHashCode();
}
}
4. Test again
After overrides both equals
and hashCode
.
User user1 = new User("mkyong", 35, "111222333");
User user2 = new User("mkyong", 35, "111222333");
System.out.println(user1.equals(user2)); // true
thanks!
If user.name or user.password is null then you get crash in equals method
In the classic way of solving this (2. Classic Way), what if user.name is null. I was doing the same method, but my problem is some fields are null in my case. Now I’ve to add null checks everywhere individually. I guess this is the Java way of dealing with null checks.
There is no need of null check in this case, just switch operands: write
name.equals(user.name)
instead of
user.name.equals(name)
But generally yes, in Java you must not use variable until it is checked for null (unless you are sure this is not the case for the variable).
I read all this, then I go to eclipse and right click > generate hashCode and Equals > select fields > done
Very good this article, really helped me. Thanks…
>>The 17 and 31 hash code idea is from the classic Java book
It would be much better if you explain what is exactly the idea, not only refer to the source and post code snippet like some dogma. In fact, there is no explanations of something (except tloszabno’s posting). This is just disappointing.
Great post. Thanks.
Thanks for sharing .
Hello,
I have one comment to this article:
if (!(o instanceof User)) – if you use “instance of” instead of class.equals you broke the symetric rule ( a.equas(b) should give same result as b.equals(a) ).
Try imagine you create new class SuperUser which extends User with one additional boolean flag “is admin”, and new equals same as above, but with additional check condition for admin flag and with “instanceof” for SuperUser.
Now create normal user = new User(“mkyong”, 35, “111222333”); and adminUser = new SuperUser(“mkyong”, 35, “111222333”)
when you invkode user.equals(adminUser) result will be true (because equals from User class will be invoked and SuperUser is “instanceof” User, and other fields – know for User – are same) but when you call adminUser.equals(user) result will be false because equals from SuperUser will be invoked and User is not “instanceof” SuperUser).
tloszabno, if you declare the override equals method final it saves the problem.
But you are right about the symmetric problem it can cause.
I think the override equals method of SuperUser is wrong, it should rely on or consider it is overriding User’s equals method
What’s the solution to this Mkyong, or tloszabno?
Should there also be a check … if (!(User instanceof o)) , so it becomes…
if (!(o instanceof User) || !(User instanceof o))
return false;
I think there should be some mention to Lombok’s
@EqualsAndHashCode
, which does correctly and efficiently.(Especially it uses
instanceof
comparision instead of “getClass()” comparision – with thecanEqual()
compensation, subtle but worth understanding)Thank you for this.