Understanding equals() and hashCode() in Java: When They Matter
This article explains the roles of equals() and hashCode() in Java, demonstrates how their interaction affects hash‑based collections like HashSet, provides multiple code examples showing correct and incorrect implementations, and outlines essential principles for overriding these methods to ensure proper object equality handling.
In Java, the equals() method determines whether two objects are considered equal, while hashCode() returns an integer used to locate the object in hash‑based collections such as HashSet or HashMap .
The article distinguishes two scenarios: (1) when a class is never stored in a hash table, hashCode() has no effect on equality; (2) when the class is used in hash‑based collections, the contract requires that equal objects have identical hash codes, otherwise duplicates may appear.
Code examples illustrate both cases. The first example ( NormalHashCodeTest ) overrides only equals() , showing that equal objects can have different hash codes, leading to duplicate entries in a HashSet . The second example ( ConflictHashCodeTest1 ) also overrides equals() but not hashCode() , still producing duplicates. The final example ( ConflictHashCodeTest2 ) overrides both methods correctly, ensuring that equal objects share the same hash code and that the HashSet contains no duplicates.
import java.util.*;
import java.lang.Comparable;
/**
* @desc 比较equals() 返回true 以及 返回false时, hashCode()的值。
*/
public class NormalHashCodeTest{
public static void main(String[] args){
// 新建2个相同内容的Person对象,
// 再用equals比较它们是否相等
Person p1 = new Person("eee", 100);
Person p2 = new Person("eee", 100);
Person p3 = new Person("aaa", 200);
System.out.printf("p1.equals(p2) : %s; p1(%d) p2(%d)\n", p1.equals(p2), p1.hashCode(), p2.hashCode());
System.out.printf("p1.equals(p3) : %s; p1(%d) p3(%d)\n", p1.equals(p3), p1.hashCode(), p3.hashCode());
}
private static class Person {
int age;
String name;
public Person(String name, int age){
this.name = name;
this.age = age;
}
public String toString(){
return name + " - " + age;
}
public boolean equals(Object obj){
if(obj == null) return false;
if(this == obj) return true;
if(this.getClass() != obj.getClass()) return false;
Person person = (Person)obj;
return name.equals(person.name) && age==person.age;
}
}
}Key principles highlighted are: (1) an object's hash code must remain constant during its lifetime; (2) equal objects must return the same hash code, though unequal objects may share a hash code (collision); and (3) whenever equals() is overridden, hashCode() must also be overridden using the same fields involved in equality checks.
IT Xianyu
We share common IT technologies (Java, Web, SQL, etc.) and practical applications of emerging software development techniques. New articles are posted daily. Follow IT Xianyu to stay ahead in tech. The IT Xianyu series is being regularly updated.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.