Do keys with different hashes also get mapped to the same index in HashMap?

前端 未结 3 1600
深忆病人
深忆病人 2021-01-13 02:43

Looking at the code specifically line 393, it looks like different hashes have been mapped to same index. I had an understanding that the hashcode is used to determine what

相关标签:
3条回答
  • 2021-01-13 03:26

    The answer is surprisingly YES. I put Sysout's in the code of put() to observe it's behaviour

    public V put(K key, V value) {
        if (table == EMPTY_TABLE) {
            System.out.println("Put: Table empty. Inflating table to threshold:" + threshold);
            inflateTable(threshold);
        }
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key);
        System.out.println("Put: Key not null:" + hash);
        int i = indexFor(hash, table.length);
        System.out.println("Put: Obtained index:" + i);
        for (Entry<K, V> e = table[i]; e != null; e = e.next) {
            System.out.println("Put: Iteraing over table[" + i + "] elements");
            Object k;
            System.out.println("Put: Checking if hash & key are equal");
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }
        System.out.println("Put: Incrementing modCounter");
        modCount++;
        System.out.println("Put: Adding a new Entry[hash="
                + hash + ", key=" + key + ", value="
                + value + ", i=" + i + "]");
        addEntry(hash, key, value, i);
        return null;
    }

    And then tested with the following inputs,

    MyHashMap p = new MyHashMap<>();
    p.put(0, "Z");
    p.put(1, "A");
    p.put(17, "A");

    And guess what the output comes

    Put: Table empty. Inflating table to threshold:16
    Inflate: RoundUpPowerOf2 of size=16
    Inflate: Setting Min of [capacity * loadFactor, MAXIMUM_CAPACITY + 1] as threshold
    Inflate: Given values[capacity=16, loadfactor=0.75, MAXIMUM_CAPACITY=1073741824
    Creating array of Entry[] with size:16
    Put: Key not null:0
    IndexFor: calculating index for [given hash=0, length=16]
    Put: Obtained index:0
    Put: Incrementing modCounter
    Put: Adding a new Entry[hash=0, key=0, value=Z, i=0]
    Put: Key not null:1
    IndexFor: calculating index for [given hash=1, length=16]
    Put: Obtained index:1
    Put: Incrementing modCounter
    Put: Adding a new Entry[hash=1, key=1, value=A, i=1]
    Put: Key not null:16
    IndexFor: calculating index for [given hash=16, length=16]
    Put: Obtained index:0
    Put: Iteraing over table[0] elements
    Put: Incrementing modCounter
    Put: Adding a new Entry[hash=16, key=17, value=A, i=0]
    
    So, as you can see, two entries got stored in the same index. Was very excited to see such behaviour. Inquisitively trying to get an answer for this.

    0 讨论(0)
  • 2021-01-13 03:30

    This check is an optimization taking into account for collisions.
    You can have 2 elements that have the same hash key (due to collision) and as a result are mapped to the same bucket. Same key different actual elements.
    So if e.hash != hash you don't need to check for equality (which could be an expensive operation)

    0 讨论(0)
  • 2021-01-13 03:41

    Since a hashcode can be one in 2^32 values, it is rare that the hashmap has so many buckets (just the table would require 16GB of memory). So yes, you can have objects with different hashes in the same buckets of the maps (AFAIK it is a simple modulus operation of hachCode % numberOfBuckets).

    Note that the code does not use directly key.hashCode(), but hash(key.hashCode()).

    0 讨论(0)
提交回复
热议问题