ankit
ankit

Reputation: 5127

ideal hash code implementation

I have class as following

public class Hash {
    int age;
    int id;
    String name;
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + id;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Hash other = (Hash) obj;
        if (id != other.id)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }


}

in this I have used only two attributes name and id to generate .equals method but now my question is. what should be a good way to implement .hashCode() method.

  1. Using only name and id
  2. Using all three name, age and id.

what are the advantages and disadvantages of both ?

Upvotes: 2

Views: 292

Answers (4)

Sage
Sage

Reputation: 15408

Without thinking too much i would use: apache's HashCodeBuilder

To use this class write code as follows:

 public class Person {
   String name;
   int age;
   boolean smoker;
   ...

   public int hashCode() {
     // you pick a hard-coded, randomly chosen, non-zero, odd number
     // ideally different for each class
     return new HashCodeBuilder(17, 37).
       append(name).
       append(age).
       append(smoker).
       toHashCode();
   }
 }

With an answer: Does only name and id uniquely identifies each object of the Class and consistent for comparison with equal() ? If yes, then why should i use three attributes instead of two?

Check this Hashing it out Article, a bit old but good details.

Upvotes: 0

Jaydeep Rajput
Jaydeep Rajput

Reputation: 3673

Implementation of hashcode method depends on how you want the bucketing to be done-

  1. One may choose to put all objects of even id in one bucket and odd id in another bucket.
    @Override
    public int hashCode() {
       return this.id % 2 == 0 ? 1 : 2;
    }
  1. Or you can choose to put people whose age is 0-10 in one bucket, 10-20 in another and so on.
    @Override
    public int hashCode() {
       return this.age / 10 ;
    }

The point is, it really depends on how your objects are spread over in range(if the objects are properly divided in buckets, you will get better performance) and how you want to do the bucketing.

Upvotes: 0

Vaibhav
Vaibhav

Reputation: 2143

I think you should use only id field only to generate hashcode if your id is unique. In this way you will be able to search your object from the collection by creating object using id only.

Also if your id is unique, we will have different hash code for different objects so it will be efficient.

Upvotes: 0

Joachim Sauer
Joachim Sauer

Reputation: 308021

An important rule for calculating hashcode is that you must only use information that's also relevant for the equals() implementation.

Since you don't use age in your equals method, it would be wrong to use it in your hashCode! The reasoning is pretty simple to follow:

  • imagine two objects o1 and o2 with the attributes "id=1, age=2, name=foo" and "id=1, age=3, name=foo".
  • calling equals() would return true
  • calling hashCode() (on an implementation that uses age) would return two different values, however!

That does not mean that you must use all such information. Sometimes it has advantages to use just a subset (for example if there is some big, hard-to-hash object that's unlikely to be the only difference between two objects).

The most primitive, correct implementation for you would be this:

public int hashCode() {
    return 0;
}

It would be correct, but terribly inefficient (because every object would hash to the same value, obviously!).

Upvotes: 3

Related Questions