Why does containsKey () Map only call hashCode ()?

I am reading the Map JavaDoc interface and it says the following:

Many methods in Framework Collections interfaces are defined in terms of an equal method. For example, a method specification containsKey(Object key)says: "returns true if and only if this card contains a mapping for the key ksuch that (key==null ? k==null : key.equals(k))." This specification should not be construed that invoking Map.containsKeywith an argument null keywill not invoke key.equals(k)to invoke any key k. Implementations implement an optimization in which a call is avoided equals, for example, by first comparing the hash codes of the two keys. (The specification Object.hashCode()ensures that two objects with unequal hash codes cannot be equal.)

My understanding is when containsKey()both hashCode () and equals () wil are called , so I wrote my own code to test it.

The HappyDay class will be stored as a key in the HashMap, I override the hashCode () and equals () methods and add System.out.println("invoking hashCode()" + this.happyHour);and System.out.println("invoking equals()");to check whether this method is called or not.

public class HappyDay {

    private final int happyHour;

    public HappyDay(int hh) {
        this.happyHour = hh;
    }

    public int getHappyHour() {
        return this.happyHour;
    }

    @Override
    public boolean equals(Object o) {
        System.out.println("invoking equals()");
        if (o == null) {return false;}

        if (o == this) {return true;}

        //this is an easy overridden, if happy hour equal, objects will be equal.
        if (o instanceof HappyDay) {
            HappyDay other = (HappyDay) o;
            int otherHappyHour = other.getHappyHour();
            if (this.happyHour == otherHappyHour) {
                return true;
            }
        }
        return false;
    }

    @Override
    public int hashCode() {
        System.out.println("invoking hashCode()" + this.happyHour);
        int hash = 7;
        hash = hash + this.happyHour;
        return hash;
    }
}

public class Main {
    public static void main(String[] args) {
        Map<HappyDay,String> hm = new HashMap<>();

        HappyDay hd1 = new HappyDay(1);
        HappyDay hd2 = new HappyDay(2);

        hm.put(hd1, "hd1");
        hm.put(hd2, "hd2");

        if(hm.containsKey(hd2)){
            System.out.println("found");
        }else{
            System.out.println("not exist");
        }
    }
}

The main class is to put two HappyDay instances in the HashMap after the insertion (put ()) method, I call hm.containsKey(hd2), as I quoted from the JavaDoc, it must first call hashCode (), and then call equals (), but the output is

invoking hashCode()1 //call put()
invoking hashCode()2 //call put()
invoking hashCode()2 //call containsKey()
found

I expect another line of output should be invoking equals(), can someone explain this to me, why is equals () not being called?

+4
2

==; , , equals.

hd2 , containsKey , , == equals .

, , , getEntry(key) null. :

360     final Entry<K,V> getEntry(Object key) {
361         int hash = (key == null) ? 0 : hash(key.hashCode());
362         for (Entry<K,V> e = table[indexFor(hash, table.length)];
363              e != null;
364              e = e.next) {
365             Object k;
366             if (e.hash == hash &&
367                 ((k = e.key) == key || (key != null && key.equals(k))))
368                 return e;
369         }
370         return null;
371     }

367 , equals ==. || equals, == , .

, , , equals (, String#equals, ). equals , o1.equals(o2) , o1 == o2, .


, :

if (hm.containsKey(new HappyDay(2))) {
    System.out.println("found");
} else {
    System.out.println("not exist");
}

:

invoking hashCode()1
invoking hashCode()2
invoking hashCode()2
invoking equals()
found

, equals. , containsKey , , == false equals.

+6

HashMap , .

containsKey getEntry:

360     final Entry<K,V> More ...getEntry(Object key) {
361         int hash = (key == null) ? 0 : hash(key.hashCode());
362         for (Entry<K,V> e = table[indexFor(hash, table.length)];
363              e != null;
364              e = e.next) {
365             Object k;
366             if (e.hash == hash &&
367                 ((k = e.key) == key || (key != null && key.equals(k))))
368                 return e;
369         }
370         return null;
371     }

, key ==. hd2, == true ( ), || , equals .

HappyDay, 2, == false equals .

, ==, , == -, equals, aren 't .

+4

Source: https://habr.com/ru/post/1541686/


All Articles