Wednesday, 8 October 2014

The methods equals and hashCode

This article explains how the object equality and their hashcode work in Java and the rules to follow when overriding the methods 'equals()' and 'hashCode()'.

The method 'equals()'


The method 'equals()' is a member of the class "Object':
    public boolean equals(Object obj);

By default, it does a type comparison with the operator ==. You can change this behaviour in order to determine if 2 objects are 'meaningfully' equivalent. Thus you can make your own rules about the conditions in which two objects of the same type should be equal.

class Person {
    private String firstName;
    private String lastName;
    private int age;

    Person (String firstName, String lastName, int age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }

    // We override the method 'equals' in order to define our own equality rules
    public boolean equals(Object obj){

        if(obj instanceof Person){

            Person person = (Person)obj;

             // Two 'Person' objects are equal if they hold identical values for the attributes 'firstName', 'lastName' and 'age':
             if( (person.firstName.equals(this.firstName)) && (person.lastName.equals(this.lastName))  && (person.age == this.age) ){
                 return true;
             }
        }

        return false;
    }
}

Let's compare 'Person' objects:
Person person1 = new Person("Joe", "Mumbace", 19);
Person Person2 = new Person("John", "Lardin", 31);
Person person3 = new Person("Sophie", "Duvallier", 31);
Person person4 = new Person("Claire", "Honton", 33);

if(person1.equals(person2)){
    System.out.println("Person1 equals to Person2");

}else if(person2.equals(person3)){
    System.out.println("Person2 equals to Person3");

}else if(person3.equals(person4)){
    System.out.println("Person3 equals to Person4");
}

Output:
   Person2 equals to Person3

Note that if you override equals you should also override an other member of the class 'Object': the method 'hascode()'.

The method 'hashcode()'

 

The method 'hashcode()' is a member of the class "Object':
public int hashCode();

An object's 'hascode' is an integer value which allows this object to be used in the Collection classes that use hashing to store and locate objects. The classes using hashing are 'HashMap', 'HashSet', 'Hashtable', 'LinkedHashMap' and 'LinkedHashSet'. These classes retrieve a member in 2 steps: they compare first the 'hashcode' of the element to search, if they find it then they compare their equality with using 'equals()' .

Three important rules:
  • if two objects are equal (with 'equals()') then their 'hashcode' should be the same: if x.equals(y) == true then x.hashcode() == y.hashcode()
  • two objects can have the same 'hashcode', they may not be equal: this is allowed, however note that your Collection will be less efficient 
  • do not make an 'hashcode' or an equality with a "transient" instance variable 
  • keep in mind that if you set an object to a collection using hashing (like an 'HashMap'), and if later the hashcode of this object change, then the you will not be able to find your object into the collection anymore. The hashcode of an object may change, for example, if the value of an instance variable involved in its calculation is modified.