Tell about the contract of hashCode and equals methods in Java.
sobes.tech AI
Answer from AI
The contract of hashCode and equals methods in Java defines their relationship and guarantees correct object behavior when using collections based on hash tables (e.g., HashSet, HashMap).
Main rules of the contract:
- Reflexivity: For any non-null reference value
x,x.equals(x)should returntrue. - Symmetry: For any non-null reference values
xandy,x.equals(y)should returntrueif and only ify.equals(x)returnstrue. - Transitivity: For any non-null reference values
x,y, andz, ifx.equals(y)returnstrueandy.equals(z)returnstrue, thenx.equals(z)should returntrue. - Consistency: For any non-null reference values
xandy, multiple invocations ofx.equals(y)should consistently return the same result, provided no information used inequalscomparisons on the objects is modified. - Non-nullity: For any non-null reference value
x,x.equals(null)should returnfalse.
And the main rule linking hashCode and equals:
- If two objects are equal according to the
equals(Object)method, then callinghashCode()on each of these objects must produce the same integer. - The reverse is not necessarily true: if two objects have the same hash code, they are not necessarily equal.
Contract significance:
Violation of the contract can lead to incorrect behavior of collections. For example, if two equal objects return different hash codes, a HashMap might place them in different "buckets" and fail to find one object by the other, even if they are logically equal.
Example of a correct implementation:
// Example class with correct equals and hashCode
public final class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Point point = (Point) o;
return x == point.x && y == point.y;
}
@Override
public int hashCode() {
int result = 17; // Magic number, usually prime
result = 31 * result + x;
result = 31 * result + y;
return result;
}
// Getters (not mandatory for equals/hashCode example)
public int getX() {
return x;
}
public int getY() {
return y;
}
}
Usage:
- Always override both methods (
equalsandhashCode) together. - When computing
hashCode, use the same fields used inequals. - Strive to create "good" hash functions that distribute hash codes evenly to minimize collisions (when different objects have the same hash code) and improve the performance of hash-based collections.
- For primitives, use their values. For objects, call their
hashCode(). For arrays, use methods fromArrays.
In Java 7+, for convenience and correctness, it is recommended to use Objects.equals(Object a, Object b) and Objects.hash(Object... values).
Example with Objects:
// Example class with equals and hashCode using Objects
import java.util.Objects;
public final class PointWithObjects {
private final int x;
private final int y;
public PointWithObjects(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PointWithObjects that = (PointWithObjects) o;
return x == that.x && y == that.y; // Comparison logic remains
}
@Override
public int hashCode() {
return Objects.hash(x, y); // Convenient method for hash calculation
}
}