Monday, May 11, 2009

hashCode and equals Methods in java classes

Often while working with objects, we want to compare whether the objects we are working with are unique or equal to each other, java has provided us with two methods in java.lang.Object and by overriding them we can compare two objects. These methods are :

1. equals method indicates whether some other object is "equal to" this one.

2. hashCode method returns a hash code value for the object, which is unique for unequal objects.

The equals method and hashCode method for any java class should go hand in hand. Any variable contributing to equals method must also be used for hashCode calculation because as per definition Objects having same hashCode should be equal to each other or conversely no two different objects may have the same hashCode.

hashCode values may also be inserted into the database as passwords and when user enters password in the application, its hashCode can be compared with the value in password field. Thus hashCode can also help with data encryption.

Here is an example on how to implement these methods.

/*

  *   @(#)Employee.java       1.1   11/05/09

  *

  *   Copyright   2009   Lazy   Coder.   All   rights   reserved.

  *   To   be   used   only   for   educational   purposes.

  *   Not   to   be   reproduced   and   published

  *   without   seeking   prior   consent.

  */


package   com.lazy.coder.examples;



/**

  *  

  *   @author   lazycoder

  *

  */




public   class   Employee   {

       private   int   empId;

       private   String   empName;



       public   boolean   equals(Object   obj)   {

              //If   this   object   and   the   Object   in   the   argument   refer   to   same   object   return   true.

              if   (this   ==   obj)

                     return   true;

              //If   obj   is   null   or   of   some   other   class   return   false.

              if   ((obj   ==   null)   ||   (obj.getClass()   !=   this.getClass()))

                     return   false;

              //   object   must   be   of   type   Employee   now

              Employee   emp   =   (Employee)   obj;

              //If   empId   =   obj.emoId   and   empName.equals(obj.empName)   return   true   else   false.

              return   empId   ==   emp.empId

                            &&   (empName   ==   emp.empName   ||   (empName   !=   null   &&   empName

                                          .equals(emp.empName)));

       }



       public   int   hashCode()   {

              int   result   =   17;

              result   =   37   *   result   +   empId;

              result   =   37   *   result   +   (empName   ==   null   ?   0   :   empName.hashCode());

              return   result;

       }

}



Here are a few tips on how to override these methods:

I. hashCode

  1. Store some arbitary constant nonzero integer value, say 17, in an int variable called result.
  2. For each significant field f in your object (each field taken into account by the equals( ) method), calculate an int hash code c for the field in the following manner:

Field type

Calculation

boolean

c = (f ? 0 : 1)

byte, char, short, or int

c = (int)f

long

c = (int)(f ^ (f >>>32))

float

c = Float.floatToIntBits(f);

double

long l = Double.doubleToLongBits(f);
c = (int)(l ^ (l >>> 32))

Object, where equals( ) calls equals( ) for this field

c = f.hashCode( )

Array

Apply above rules to each element

  1. Combine the hash code(s) computed above:
    result = 37 * result + c;
    where 37 can be replaced with any primary number
  2. Return result.
  3. Look at the resulting hashCode( ) and make sure that equal instances have equal hash codes.
II. equals
  1. Use the equality == operator to check if the argument is the reference to this object, if yes. return true. This saves time when actual comparison is costly.
  2. Check that the argument is not null and it is of the correct type, if not then return false.

    Note that, correct type does not mean the same type or class. It could be any class or interface that one or more classes agree to implement for providing the comparison.
  3. Compare significant variables of both, the argument object and this object and check if they are equal. If *all* of them are equal then return true, otherwise return false. Again, as mentioned earlier, while comparing these class variables; primitive variables can be compared directly with an equality operator (==) after performing any necessary conversions (Such as float to Float.floatToIntBits or double to Double.doubleToLongBits). Whereas, object references can be compared by invoking their equals method recursively. You also need to ensure that invoking equals method on these object references does not result in a NullPointerException.
  4. Do not change the type of the argument of the equals method. It takes a java.lang.Object as an argument, do not use your own class instead. If you do that, you will not be overriding the equals method, but you will be overloading it instead; which would cause problems.


Digg Technorati Delicious StumbleUpon Reddit BlinkList Furl Mixx Facebook Google Bookmark Yahoo
ma.gnolia squidoo newsvine live netscape tailrank mister-wong blogmarks slashdot spurl

1 comment:

  1. Your uniqueness comments regarding hashcodes is wrong. Equal objects should have equal hashcodes. But, two objects with equal hashcodes are not necessarily equal objects.

    A hashcode is an int.

    But, for example, a java.lang.Long object has a hashcode. Since there are more Long values than there are int values, multiple Long values must have the same hashcode. This is an example of the Pigeonhole Principle: http://en.wikipedia.org/wiki/Pigeonhole_principle

    Each pigeonhole here is a single 'int' value that could be returned from a hashCode method.

    ReplyDelete