Showing posts with label hashcode. Show all posts
Showing posts with label hashcode. Show all posts

Sunday, 15 May 2011

Useful steps in implementing your own hashCode() method

Here are some useful guidelines for implementing the hashCode method correctly.

  1. Store an arbitrary non-zero constant integer value (say 7) in an int variable, called hash.
  2. Involve significant variables of your object in the calculation of the hash code, all the variables that are part of equals comparison should be considered for this. Compute an individual hash code int var_code for each variable var as follows -
    1. If the variable(var) is byte, char, short or int, then
      var_code = (int)var;


    2. If the variable(var) is long, then

      var_code = (int)(var ^ (var >>> 32));


    3. If the variable(var) is float, then

      var_code = Float.floatToIntBits(var);


    4. If the variable(var) is double, then -

      long bits = Double.doubleToLongBits(var);
      var_code = (int)(bits ^ (bits >>> 32));


    5. If the variable(var) is boolean, then

      var_code = var ? 1 : 0;


    6. If the variable(var) is an object reference, then check if it is null, if yes then var_code = 0; otherwise invoke the hashCode method recursively on this object reference to get the hash code. This can be simplified and given as -

      var_code = (null == var ? 0 : var.hashCode());


  3. Combine this individual variable hash code var_code in the original hash code hash as follows -

    hash = 31 * hash + var_code;


  4. Follow these steps for all the significant variables and in the end return the resulting integer hash.
  5. Lastly, review your hashCode method and check if it is returning equal hash codes for equal objects. Also, verify that the hash codes returned for the object are consistently the same for multiple invocations during the same execution.
The guidelines provided here for implementing equals and hashCode methods are merely useful as guidelines, these are not absolute laws or rules. Nevertheless, following them while implementing these two methods will certainly give you correct and consistent results.






Saturday, 14 May 2011

Implementing hashCode using commons-lang

This example shows how to implement hashCode() using HashCodeBuilder of commons-lang.

import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.EqualsBuilder;

import java.io.Serializable;

public class MyClass implements Serializable {
private Long id;

private String title;

private String author;

public int hashCode() {
return new HashCodeBuilder().append(id).append(title).append(author).toHashCode();

// return HashCodeBuilder.reflectionHashCode(this);

}
}

 

Also, reflection can be used to implement the same function:


public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}


Use of hashcode and equals


Tuesday, 15 February 2011

Implementing Hashcode

Implementing hashCode :
  • if a class overrides equals, it must override hashCode
  • when they are both overridden, equals and hashCode must use the same set of fields
  • if two objects are equal, then their hashCode values must be equal as well
  • if the object is immutable, then hashCode is a candidate for caching and lazy initialization
Misconception:

It is a popular misconception that hashCode provides a unique identifier for an object. It does not.

Cases of Inconsistency when not implementing equals() or hashCode() OR Why we need to override equals and hashCode() method

When implementing hashCode() but not equals()

public class MyString {



private String inputString;



public MyString(String string) {

inputString=string;

}



@Override

public int hashCode() {

return inputString.length();

}

}


 


Now lets see the result with tester class:


public static void main(String[] args) {



MyString obj1 = new MyString (“my-string”);

MyString Obj2 = new MyString (“my-string”);

if(obj1.hashCode() == obj2.hashCode()){

System.out.println(“HashCode are equal”);

}

if(obj1.equals(obj2)){

System.out.println(“Objects are equal”);

}else{

System.out.println(“Objects are not equal”);

}



}



Case when not implementing hashCode()


If the object does not implement hashcode() method and used as key then we will not get the object back as shown in below code.


class Person{
private String name;
private boolean gender;//false for female, true for male
//some getters and setters
//no equals and hashcode implemented in this class
}



Now using this class:


public class HashMapDemo {

public static void main(String[] args) {
Person person=new Person("ramesh",true);
Person person2 = new Person("ramesh",true);
Person person3 = new Person("suresh",true);
Person person4 = new Person("kavya",false);

HashMap<Person, String> map = new HashMap<Person, String>();
//Note that 2 duplicate object added to hashmap and no exception thrown...
map.put(person,"New person");
map.put(person2,"Duplicate person");
map.put(person3,"Another new person");
map.put(person4,"new Female person");

//
//Now retrieving the hashmap
Person rameshAgain=new Person("ramesh",true);
if(map.get(rameshAgain) == null)
System.out.println("Object not found");
else
System.out.println("Our object found in map");
}



Output:


Object not found



As you can see in above program :


  1. Duplicate objects are added in Hashmap as a key (Because we have not overided the hashcode and equals method)
  2. We are not able to get back object from map (Because hashcode is not implemented)

Some guidelines for implementing hashCode()


 


Implementing the hashCode() and equals()


Now implementing hashCode() and equals:


public class Person {

int id;

String name;

public boolean equals(Object obj){

if(this == obj) return true; // if both are referring to the same object
if ((obj == null) || (obj.getClass() != this.getClass())) {
return false;
}
Person rhs = (Person) obj;
return id == rhs.id &amp;&amp; (name == rhs.name ||
(name != null &amp;&amp; name.equals(rhs.name)) );

}

//both fields id &amp; name are used in equals(), so both fields must be used in

//hashCode() as well.

public int hashCode() {

int hash = 9;

hash = (31 * hash) + id;

hash = (31 * hash) + (null == name ? 0 : name.hashCode());

return hash;

}

}