Categories
Java

Overriding the equals() and hashCode() methods

The equals() method is inherited from the superclass Object and determines if two instances are equal or equivalent.
Usually this method should be overridden because the equals() method of the Object class is equivalent to the operator ==, which returns true if and only if the two references refer to the same object.
Look at the following code:

  • file eu/lucazanini/circle/Main.java
  • file eu/lucazanini/circle/Circle.java

The output of this example is:

If you want the equals() returns true when the circles have the same radius and color, then you need to override it in the Circle class:

The resulting output is:

Note that it is good practice to verify that the object passed to equals() is the desired type (obj instanceof Circle), and only then verify that the condition for equality (radius == circle.getRadius() && color.equals(circle.getColor())).
The condition for equality must comply with the equals() contract that must be:

  • reflexive: ∀ x, x.equals(x) == true
  • symmetric: ∀ x y, x.equals(y) ⇔ y.equals(x)
  • transitive: ∀ x y, x.equals(y) and y.equals(z) ⇔ x.equals(z)
  • consistent: for any x e y multiple invocations of x.equals(y) always returns the same value if no information about x and y used in equals() is modified
  • ∀ x not null, x.equals(null) == false

When 2 objects are equal according to the equals() then also their hash codes must be equal, so it is a good practice, when you override equals(), also override hashCode(), a method inherited from the superclass Object.
In the implementation in Object, hashCode() returns an integer different for each object, but in general it is possible that different objects share the same hash code although this makes the code less efficient.
Another advantage in the override hashCode() is a more efficient search in Collections as HashMap or HashSet that use the hash code in the management of objects.
The contract for hashCode() with the following points:

  • consistent: hashCode() always returns the same integer for the same object if the information used in equals() is not modified (the integer returned can change between different executions of the application)
  • ∀ x y, x.equals(y) == true ⇔ hashCode(x) == hashCode(y)
  • x.equals(y) == false does not imply that the hash codes are different

Also hashCode() should use the same information used by equals().
Look at the implementation of equals() and hashCode() in this example:

  • file eu/lucazanini/circle/Main.java
  • file eu/lucazanini/circle/Circle.java

The output is:

Note that circles with different radius or color may have the same hash code but equal circles must always have the same hash code.
There are other ways of implementing hashCode(), also an implementation that always returns the same integer as in the following example is legal:

This example does not violate the hashCode() contract but it is a very inefficient and useless implementation.

References:
Object as a Superclass

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.