In Java, every object extends java.lang.Object
class. One of the main methods of this class is the equals method which as Javadoc says:
“Indicates whether some other object is ‘equal to’ this one”.
Let’s start with some basics. In its default implementation, the equals method compares references between two objects. On the other hand, it is often highly desirable to override this method to make object equality consistent with imposed business logic. Suppose we have a Person class with two attributes: “name” and “surname”:
public class Person {private String name;private String surname;}
If we compare two objects of this class which have the same “name” and “surname” the result will be false, because the objects have different references.
Person person1 = new Person("John", "Kowalski");Person person2 = new Person("John", "Kowalski");System.out.println(person1.equals(person2)); // false
In order to make objects equal based on their attribute values, we have to override the equals method from the Person class:
@Overridepublic boolean equals(Object obj) {if (this == obj) return true;if (obj == null) return false;if (getClass() != obj.getClass()) return false;Person other = (Person) obj;if (name == null) {if (other.name != null) return false;} else if (!name.equals(other.name)) return false;if (surname == null) {if (other.surname != null) return false;} else if (!surname.equals(other.surname)) return false;return true;}
Now two objects of the Person class will be equal if they have the same “name” and “surname” value:
Person person1 = new Person("John", "Kowalski");Person person2 = new Person("John", "Kowalski");System.out.println(person1.equals(person2)); // true
As far as we can just override the equals method, it is strongly recommended to override the hashCode method whenever the equals method is overridden. This is associated with one of the contract’s points for hashCode method, which is stated in Javadoc as follows:
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
By default, the hashCode method returns converted to integer object memory address- taking this into account as well as the contract point mentioned above, it implies that the hashCode method has to be overridden whenever the equals method is overridden- otherwise hashCode method for every new object will return different value regardless of class attributes values and that breaks the contract.
What is even more interesting, another point of the contract for hashCode method says, that it is NOT required for two objects that are not equal, to return different value from hashCode method:
It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.
To understand why is, we have to understand the hashCode method’s general purpose. HashCode method is used in
data structures based on hashing, like java.util.HashMap
or java.util.HashSet
.
Data structures based on hashing are key-value type structures. For every key, there is a generated integer,
which represents the index under which the value from the key-value pair is stored. Retrieving the value for the
specific key is fast- you just have to generate the hash value for the key and retrieve data from the table for the obtained index.
In practice, sometimes may happen that for different input values hashCode method can return the same value-
this kind of situation is called collision. Collisions are undesirable, as they make different keys to be
associated with the same table index. Java solves this problem by storing in every table record not a value,
but a list of values. If two different objects have the same value returned by the hashCode method, they are
stored in a list, where the list is stored in a table record under the index equal to its object hashCode value:
When data for the specific key is retrieved and the hashCode value for this key does not indicate a single value but a list of values caused by the collision, then the linear search takes place: every element of the list is compared with the key using equals method, until the key is found. Linear search is much slower than retrieving data for specific indexes from a table, therefore it is highly desirable to avoid collisions which can be achieved by implementing the hashCode method in a proper way. You can find some tips on how to implement the hashCode method on stackoverflow: link.
Quick Links
Legal Stuff