Exploring Java 8 equals() and hashCode() Methods
Written on
Understanding the equals() Method
In the Java Object class, the equals() method is defined as follows:
public boolean equals(Object obj) {
return (this == obj);
}
This implementation utilizes the "==" operator, which checks if both objects share the same memory address. Hence, they are considered equal only if they point to the same location in memory.
What is hashCode()?
Similarly, the hashCode() method in Object.java is declared as a native function:
public native int hashCode();
According to its documentation, hashCode() returns a hash code value for the object, which is particularly useful for hash tables like those implemented in java.util.HashMap. The primary purpose of hashCode() is to facilitate operations in hash-related classes such as HashMap, HashSet, HashTable, and ConcurrentHashMap.
Key Questions to Ponder
If two objects share the same hash code, are they equal?
Not necessarily. Since hashCode() generates a 32-bit integer, it's possible for different objects to have identical hash codes. A fitting analogy is that sharing a birthday does not imply two people are the same.
Conversely, if two objects are equal, do they share the same hash code?
Yes, they must. Equal objects refer to the same memory address, leading to identical hash codes.
The Necessity of Both equals() and hashCode()
While reflecting on this topic, I questioned the need for hashCode() if equals() suffices for object comparison. The hashCode() method is crucial for efficient operations within hash-related classes. For example, in a HashMap, a code segment checks the hash value before performing more detailed comparisons:
node.hash == hash && (node.key == key || (key != null && key.equals(node.key)))
Here, the first comparison involves the hash values, providing a quick means to determine if two objects could be equal. If the hash values differ, the comparison can short-circuit, enhancing performance. Only when the hash values match is a further check for equality necessary.
Overriding equals()
When overriding the equals() method, it is essential to also override hashCode() to maintain the contract that equal objects must yield equal hash codes. This is critical for the integrity of hash-based collections.
#### Case Study: Overriding Equals without hashCode()
Consider the following class definition for an Order object:
public class Order {
private int orderId;
private String item;
public Order(int orderId, String item) {
this.orderId = orderId;
this.item = item;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Order order = (Order) o;
return orderId == order.orderId;
}
}
In a testing scenario, we create two Order instances with the same orderId but different items:
public void test() {
HashSet<Order> orders = new HashSet<>();
Order orderA = new Order(1, "bread");
Order orderB = new Order(1, "butter");
orders.add(orderA);
orders.add(orderB);
System.out.println(orderA.equals(orderB));
System.out.println(orders.size());
}
The output indicates that the two orders are deemed equal, yet the HashSet size remains 2, showcasing a violation of the equals/hashCode contract. This discrepancy arises because hashCode() has not been overridden, causing HashMap to treat both orders as distinct due to differing references.
Implementing hashCode()
To resolve this, we can override the hashCode() method:
@Override
public int hashCode() {
return Objects.hash(orderId);
}
Upon re-executing the application:
// New output
The output will now show that both orderA and orderB are equal, and the HashSet contains only one order, as expected. This is due to both orders generating the same hash code, confirming their equality.
This article aims to enhance your understanding of backend software engineering, specifically around Java's equals() and hashCode() methods. I share insights on Java, SQL, design patterns, and best coding practices weekly. Follow along for more updates on backend engineering.
Read More:
- How to Implement Deep Copy of An Object in Java
- How to Auto-Generate Repetitive Java Code to Save Time
This video provides an in-depth exploration of the hashCode method in Java, illustrating its significance within the Object class.
This video explains the equals and hashCode contract in Java programming, emphasizing the importance of both methods in maintaining object equality within collections.