When working with Java objects, youāll often need to compare them ā not just by memory reference, but by their actual content.
Thatās where equals()
and hashCode()
come in. These two methods are crucial for object comparison, especially when using Java collections like HashMap
, HashSet
, or Hashtable
.
š§© What Are equals()
and hashCode()
?
Both equals()
and hashCode()
are methods inherited from Javaās Object class ā the root of all Java classes.
public boolean equals(Object o);
public int hashCode();
⤠equals()
The equals()
method compares two objects logically ā meaning, it checks whether the values inside the objects are the same, not just whether they occupy the same memory address.
Example 1: String Comparison
String s1 = new String("Hello");
String s2 = new String("Hello");
System.out.println(s1.equals(s2)); // true
System.out.println(s1 == s2); // false
Explanation:
equals()
checks the value, while ==
checks the memory reference.
Since String
overrides equals()
internally to compare character sequences, s1.equals(s2)
returns true
.
Hereās how the String
class overrides equals()
:
public boolean equals(Object anObject) {
if (this == anObject) return true;
if (anObject instanceof String) {
String aString = (String) anObject;
return coder() == aString.coder()
? StringLatin1.equals(value, aString.value)
: StringUTF16.equals(value, aString.value);
}
return false;
}
Example 2: Custom Class Without Overriding equals()
class Person {
private String name;
private int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
}
Person p1 = new Person("Suresh", 25);
Person p2 = new Person("Suresh", 25);
System.out.println(p1.equals(p2)); // false
System.out.println(p1 == p2); // false
Explanation:
Since Person
doesnāt override equals()
, it uses the default version from the Object
class, which compares memory references ā not values.
Hence, both comparisons return false
.
Letās fix that:
@Override
public boolean equals(Object obj) {
if (obj instanceof Person) {
Person p = (Person) obj;
return this.name.equals(p.name) && this.age == p.age;
}
return false;
}
Now, comparing p1.equals(p2)
will return true
.
⤠hashCode()
The hashCode()
method returns an integer hash value representing the object.
Itās used mainly in hash-based collections, such as:
HashMap
HashSet
Hashtable
The hash code determines where an object is stored inside these data structures.
š The Contract Between equals()
and hashCode()
Thereās a fundamental rule in Java:
If two objects are equal according to
equals()
, they must have the samehashCode()
.
In other words:
if (a.equals(b)) {
assert a.hashCode() == b.hashCode(); // must be true
}
However, the reverse is not always true ā two unequal objects can have the same hash code (known as a hash collision).
š” Why It Matters (Real-World Use Cases)
ā Use Case: Storing Objects in Hash Collections
When you add an object to a HashSet
or use it as a key in a HashMap
, Java does the following:
- Calls
hashCode()
ā to find the bucket where the object should go. - Calls
equals()
ā to check if an identical object already exists in that bucket.
If you donāt override these methods correctly, duplicate or missing data issues can occur.
Example:
class Person {
String name;
Person(String name) { this.name = name; }
}
Person p1 = new Person("Alice");
Person p2 = new Person("Alice");
HashSet<Person> set = new HashSet<>();
set.add(p1);
System.out.println(set.contains(p2)); // false! equals/hashCode not overridden
š ļø Correct Way to Override equals()
and hashCode()
class Person {
String name;
Person(String name) { this.name = name; }
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof Person)) return false;
Person other = (Person) obj;
return name.equals(other.name);
}
@Override
public int hashCode() {
return name.hashCode();
}
}
Now this will work as expected:
HashSet<Person> set = new HashSet<>();
set.add(p1);
System.out.println(set.contains(p2)); // true
System.out.println(p1.equals(p2)); // true
š§ Summary Table: equals() vs hashCode()
Method | Purpose | Common Use Case |
---|---|---|
equals() |
Compares two objects logically | Used for content comparison |
hashCode() |
Generates a unique integer value | Used in HashMap , HashSet , etc. |
š Key Takeaways
- Always override both
equals()
andhashCode()
when creating custom classes. - Use consistent logic in both methods.
- Remember: Equal objects must have the same hash code.
- Improper overriding can lead to bugs in collections and unexpected behavior.
š Further Reading
- Java Documentation: Object class
- [Effective Java by Joshua Bloch ā Item 11: Always override hashCode when you override equals]
In short:
If your class objects are meant to be compared or stored in sets/maps ā never forget to properly override equals()
and hashCode()
. Itās a small step that prevents big headaches later.