user2269170
user2269170

Reputation: 79

overriding equals issue in hashmap

I am facing some problem while overriding the equals method. Here is my code as below:

import java.util.HashMap;
import java.util.Map;

public class HashCodeTest {

public static void main(String[] args) {
    Employee emp1=new Employee();
    emp1.setName("emp1");

    Employee emp2=new Employee();
    emp2.setName("emp2");

    Employee emp3=new Employee();
    emp3.setName("emp3");

    Map map=new HashMap<Employee,String>();
    System.out.println("put a");
    map.put(emp1, "a");
    System.out.println("put b");
    map.put(emp2, "b");
    System.out.println("put c");
    map.put(emp3, "c");

    System.out.println();
    System.out.println("map element are "+map);
    System.out.println("get 3rd obj");
    System.out.println("map element are "+map.get(emp3));
    System.out.println();

    System.out.println("get 2nd obj");
    System.out.println("map element are "+map.get(emp2));
}

}

class Employee 
{

.
.
getters and setters

@Override
public int hashCode()
{
System.out.println("hashcode called");
return 12;
}
@Override
public boolean equals(Object str)
{
System.out.println("equal called");
return false;
}
}

It produces the output as:

put a
hashcode called
put b
hashcode called
equal called
put c
hashcode called
equal called
equal called

map element are {name   emp3=c, name   emp2=b, name   emp1=a}
get 3rd obj
hashcode called
map element are c

get 2nd obj
hashcode called
equal called
map element are b

I have overridden equals method that always return false and hashcode method always return the same value. So, as per this each object will fall on same bucket. But my problem is that i am not able to understand when equals method always return false then why it is able to give the correct output that matches the key.

Please Help. Thanks in advance.

Upvotes: 1

Views: 85

Answers (3)

Rais Alam
Rais Alam

Reputation: 7016

The hashmap checks reference equality first, and if that passes, it skips the .equals call. This is an optimization and works because the contract of equals specifies that if a == b then a.equals(b).

Upvotes: 1

SKU_MIG
SKU_MIG

Reputation: 21

Try this -

Employee emp2x=new Employee(); emp2x.setName("emp2");

System.out.println("map element are "+map.get(emp2x));

Upvotes: 0

wero
wero

Reputation: 32980

If you look into the HashMap implementation you find this method which does the actual lookup:

final Node<K,V> getNode(int hash, Object key) {
    Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
    if ((tab = table) != null && (n = tab.length) > 0 &&
        (first = tab[(n - 1) & hash]) != null) {
        if (first.hash == hash && // always check first node
            ((k = first.key) == key || (key != null && key.equals(k)))) // !
            return first;
        if ((e = first.next) != null) {
            if (first instanceof TreeNode)
                return ((TreeNode<K,V>)first).getTreeNode(hash, key);
            do {
                if (e.hash == hash &&
                    ((k = e.key) == key || (key != null && key.equals(k)))) // !
                    return e;
            } while ((e = e.next) != null);
        }
    }
    return null;
}

The key is compared by reference first (see //!) and then by equality. So it returns the right value despite your faulty equals implementation.

Upvotes: 4

Related Questions