Saturday, August 10, 2013

Java - Overriding hashCode() and equals()

Java provides a convenient way to calculate 'deep comparison' of objects via hashCode() and equals() methods. Every object has the default implementation for these methods. Deep comparison of objects can be implemented by overriding hashCode() and equals() methods. Several rules are defined by Java creators which we go through in the following sections. You can access these rules from Javadocs of Object.

Rules to override hashCode()

  1. Invocations of hashCode() should return the same value when fields of object do not change
  2. If two objects are equal based on equals() method, both the objects should return the same hashCode()
  3. It is not required that the hashCode() be dissimilar when two objects are not equal based on equals()

Rules to override equals()

  1. Reflexive: An object should be equal to itself: a.equals(a) is true
  2. Symmetric: If an object is equal to another object based on equals(), then these objects should be equal irrespective of which object's equal method is called: => if a.equals(b) is true then b.equals(a) is also true 
  3. Transitive: if two objects are equal based on equals(), then these objects are equal to any other objects that are equal to any of these objects: if a.equals(b) is true and b.equals(c) is true, then a.equals(c) is true
  4. Consistent: multiple invocations of equals() on objects should return the same value, if the underlying values used to check equality are not modified
  5. Equality check with null is false 

Example: Consider the following class that contains an int and the way hashCode() and equals() are overridden.

    class A
    {
        int x;
        public int setX(int x);
        {
            this.x = x;
        }
        public int getX()
        {
            return this.x;
        }
        public int hashCode()
        {
            return x;
        }
        public int equals(Object object)
        {
            boolean isEqual = true;
            if(object == null)
            {
                isEqual = false;
            }
            else if(Class.forName(object) != this.class))
            {
                isEqual = false;
            }
            else
            { 
                A compareObject = (A) object;
                if(this.x != compareObject.x)
                {
                    isEqual = false;
                }
            }
            return isEqual;
        }
    }

Verify that the rules for hashCode() and equals() are satisfied: Example:

A a,b,c,d;
a.setX(5);
b.setX(5);
c.setX(5);
d.setX(6);

Rules for hashCode():
  1. a.hashCode() will always return 5
  2. a.equals(b) is true. also, a.hashCode() and b.hashCode() return 5
  3. a.equals(d) is false (5 != 6). though a.hashCode() can be same as d.hashCode(), in our implementation they are different

Rules for equals():
  1. a.equals(a) will always return true
  2. a.equals(b) is true and b.equals(a) is true
  3. a.equals(b) is true and b.equals(c) is true and c.equals(a) is also true
  4. a.equals(b) is true as long as the 'x' value of the objects is not changed
  5. a.equals(null) is false

No comments:

Post a Comment