Ashwin
Ashwin

Reputation: 13517

Working of hashcode() and equals() in java?

This is the class that we will use to put into a hasmap. It has overriden both equals() and hashcode() methods.

class Dog
    {
        public String name;
        public Dog(String n)
        {
            name=n;
        }
        @Override
        public int hashCode() {
            System.out.println("in hashcode");
            return name.length();
        }
        @Override
        public boolean equals(Object obj) {
            System.out.println("in equals");
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Dog other = (Dog) obj;
            if (name == null) {
                if (other.name != null)
                    return false;
            } else if (!name.equals(other.name))
                return false;
            return true;
        }


    }

This code in main

Map<Object,Object> m=new HashMap<Object,Object>();
        Dog d1=new Dog("clover");
        m.put(d1,"Dog Key");
        System.out.println(m.get(d1));

produces

in hashcode
in hashcode
Dog Key

but the following code

Map<Object,Object> m=new HashMap<Object,Object>();
        Dog d1=new Dog("clover");
        m.put(d1,"Dog Key");
        System.out.println(m.get(new Dog("clover")));

produces

in hashcode
in hashcode
in equals
Dog Key

As you can see there is a call to equals() method in the second output. Why is that so?
My second question
If I change the name attribute of the key Map m=new HashMap();

Dog d1=new Dog("clover");
        m.put(d1,"Dog Key");

        d1.name="arthur";
        System.out.println(m.get(new Dog("clover")));

the o/p is

in hashcode
in hashcode
in equals
null

even though I have changed the key value, but I am trying to retrieve the value by giving an identical key. Then why does it retrieve null?

Upvotes: 1

Views: 287

Answers (3)

wolfroma
wolfroma

Reputation: 154

Lets consider how HashMap works.

  1. Many objects can have the same hashCode. When do you put an object into the map, it builds a table is based on result of hashCode method. HashMap stores objects with same hashCode in a list and every such list is attached to the table with a cell associated with particular hashCode.
  2. When do you get an object from the map, it evaluates a hashCode of a passed key object and then get a list of objects is associated with given hashCode. Then it finds object in the list using equals method.

Using proper hashcode alghorithm and capacity settings for the HashMap allows to reach O(1) performace on put and get in general.

Now lets consider your questions:

  1. You go put then get from hashMap. You see a "in equals" statement becuase you have a different object for key. There is a bit of optimisation when keys are the same, HasMap doesn't call equals method in that case. In first case d1 == d1, but d1 != new Dog("clover") for second one.
  2. Your objects have the same hashCode but they are no longer equals. And keys are different

But if you change your code in this:

Dog d1=new Dog("clover");
    m.put(d1,"Dog Key");

    d1.name="arthur";
    System.out.println(m.get(d1));

It should give you atrhur in the end.

Upvotes: 1

svz
svz

Reputation: 4588

This is because after you put your d1=new Dog("clover") into hashmap, you change its name by d1.name="arthur"; so Dog with name arthur is no longer equal to new Dog("clover").

So at first the key hashcode is checked first and it matches as "clover".length is equal to "arthur".length and this lets identify the bucket where your object is held. After that an equals() check is performed to get the right object from the bucket and this fails as your key is not equal to the one provided.

Actually, it is not a good practice to use mutable fields for hashcode calculation.

Upvotes: 1

Ernest Friedman-Hill
Ernest Friedman-Hill

Reputation: 81684

For the first question: the HashMap needs to call equals() to confirm that the two Dog objects which both have the same hash code are in fact equal. It doesn't need to call equals() the first time because it uses == to check for the special case of using the exact same object as previously specified.

For the second question: you changed a data member which changes the calculation of the hash code and the result of equals(). This is specifically against the rules, and as a result the map is corrupted; at that point, anything can happen. Never use objects with mutable data for keys in a HashMap!

Upvotes: 3

Related Questions