Anand
Anand

Reputation: 21348

Java objects are equal though hashcode is different

While reading about equals() and hashcode(), I came to know that if two objects are equal, then their hashcodes must be equal, though not vice-versa.

But below example doesn't reflect this.

class Employee{

  private String name;

  Employee(String name){
    this.name = name;
  }

  @Override
  public boolean equals(Object obj) {           
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Employee other = (Employee) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }

}

Now if I create two Employee objects as

Employee e1 = new Employee("hi");
Employee e2 = new Employee("hi");

If i do, e1.equals(e2), it returns true even though their hashcodes are different which is evident from printing, e1.hashcode() and e2.hashcode().

Can someone explain me?

Upvotes: 3

Views: 11700

Answers (4)

Tushar Paliwal
Tushar Paliwal

Reputation: 301

You should override hashcode methode. 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

Upvotes: 0

Amit Deshpande
Amit Deshpande

Reputation: 19185

You need to override hashcode method and provide implementation which is in contract with equals.

   @Override
    public int hashCode() {
        return name == null ? 0 : name.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

You can read about implementing hashcode here

If you don't override the method default behavior will be used from Object class.

As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTM programming language.)

Hash based [HashMap,HashSet,Hashtable,LinkedHashSet,WeakHashMap] collections will use hashCode() to find/store objects in buckets and then they will call equals().

Upvotes: 11

Rohit Jain
Rohit Jain

Reputation: 213371

This is because, everytime you override equals method you must also override hashcode method.

Else, your objects will be compared according to your code, but their HashCode will be calculated according to the pre-defined algorithm in the Object class.

NOTE: - In general, what all parameters you have considered in checking whether your objects are equals or not, you should use all those parameters to calculate the hashcodes for each object.

See this very good post which describes the use of equals and hashcode method.

To quote a line from this post, that I already described above: -

Use same set of fields to compute hashcode that you used in equals method

Let's see the below Demo to understand the above statement: -

public class Demo {
    private String str;
    private String name;

    public boolean equals(Object obj) {
        // Suppose you compare two objects based on length of their name variable

        // If name equals, object are equal
        if (obj instanceof Demo) {
            return this.name.equals(((Demo)obj).name);
        }
        return false;
    }

    // ****** Badly Overrided hashcode *******
    public int hashcode() {
        // But you calculate hashcode using both the fields

        // You should never use this kind of code in hashcodes. 
        // Use complex algorithm which gives you distinct result for 
        // objects that are not equal.
        return str.length + name.length;
    }
}

So, If the two objects have same name, then they would be equal, but still if their str field has different length, then their hashcodes will be different.

That is why, you should always use the same fields in equals and hashcode calculation.

Upvotes: 3

pb2q
pb2q

Reputation: 59637

You'll need to also override hashCode to get the behavior that you expect. The default implementation of Object.hashCode is probably returning the object references, although according to the docs this isn't required.

Without overriding hashCode you can't expect specialized results; this is analogous to overriding equals.

Upvotes: 0

Related Questions