简体   繁体   中英

what happend when the Map's containsKey(E e) is called in Java


i've checked the source code :

    public boolean containsKey(Object key) {
        Iterator<Map.Entry<K,V>> i = entrySet().iterator();
        if (key==null) {
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                if (e.getKey()==null)
                    return true;
            }
        } else {
            while (i.hasNext()) {
                Entry<K,V> e = i.next();
                if (key.equals(e.getKey())) 
                    return true;
            }
        }
        return false;
    }


 public boolean equals(Object obj) {
        return (this == obj);
    }

from the source code , it shows only the "equal()" method has been called , so if i wanna put an custom Object in a map , i could only have to override the "equal()" method. so i did an experiment , the result is negative ... i have to override both "equals()" and "hashCode()" . so my question is :

  1. why both method (equals() ,hashCode()) has to be override.
  2. does the "==" operation internally calls the "hashCode()" method?

This is AbstractMap 's implementation. HashMap , which overrides it, implements it as follows:

public boolean containsKey(Object key) {
    return getEntry(key) != null;
}

final Entry<K,V> getEntry(Object key) {
    if (size == 0) {
        return null;
    }

    int hash = (key == null) ? 0 : hash(key);
    for (Entry<K,V> e = table[indexFor(hash, table.length)];
         e != null;
         e = e.next) {
        Object k;
        if (e.hash == hash &&
            ((k = e.key) == key || (key != null && key.equals(k))))
            return e;
    }
    return null;
}

final int hash(Object k) {
    int h = hashSeed;
    if (0 != h && k instanceof String) {
        return sun.misc.Hashing.stringHash32((String) k);
    }

    h ^= k.hashCode();

    // This function ensures that hashCodes that differ only by
    // constant multiples at each bit position have a bounded
    // number of collisions (approximately 8 at default load factor).
    h ^= (h >>> 20) ^ (h >>> 12);
    return h ^ (h >>> 7) ^ (h >>> 4);
}

As you can see, this depends on the hashCode() . Other map types may indeed not depend on this method being overriden.

  1. From Object.equals API: it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes. You can find more detailed explanation in "Effective Java" Item 9: Always override hashCode when you override equals.

  2. No it does not, it is simply pointers comparison, just like comparing two ints

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM