0

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?
Adams.H
  • 1,603
  • 4
  • 20
  • 29
  • 1
    Which _set_ implementation did you use for your test? I guess _HashSet_. From which _set_ implementation does the source come? I guess _AbstractSet_. – nosid Mar 01 '14 at 09:19
  • 1
    1) a hashmap uses smarter logic to get faster results. 2) no, it does not call hashcode or anything else; it is a basic operator. – Dave Mar 01 '14 at 09:24
  • @nosid he's talking about a `Map`, so I guess he's thinking about a `HashMap` while the source code he shows us is from `AbstractMap`. Different class, different implementation indeed. He needs to look at `HashMap.containsKey` – Erwin Bolwidt Mar 01 '14 at 09:46
  • @Erwin Bolwidt you're right , i should have check the HashMap's implementation ...tks ! – Adams.H Mar 01 '14 at 09:49

2 Answers2

3

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.

Mureinik
  • 297,002
  • 52
  • 306
  • 350
3
  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

Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275