简体   繁体   English

具有不同哈希值的键是否也映射到HashMap中的相同索引?

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

Looking at the code specifically line 393, it looks like different hashes have been mapped to same index. 特别是在第393行查看代码时,看起来不同的哈希值已映射到相同的索引。 I had an understanding that the hashcode is used to determine what bucket in a HashMap is to be used, and the bucket is made up of a linked list of all the entries with the same hashcode. 我理解哈希码用于确定要使用HashMap中的哪个存储桶,并且存储桶由具有相同哈希码的所有条目的链表组成。 They why have the e.hash == hash check ? 他们为什么要进行e.hash == hash检查?



    public V put(K key, V value) {
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key.hashCode());
        int i = indexFor(hash, table.length);
        for (Entry e = table[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }
        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }

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). 由于哈希码可以是2 ^ 32个值中的一个,因此很少有哈希值具有如此多的桶(只需要该表需要16GB的内存)。 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 ). 所以,是的,您可以在地图的相同存储区中使用具有不同哈希值的对象(AFAIK,它是hachCode % numberOfBuckets的简单模数运算)。

Note that the code does not use directly key.hashCode() , but hash(key.hashCode()) . 请注意,代码不直接使用key.hashCode() ,而是使用hash(key.hashCode())

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. 您可以拥有2个具有相同散列键的元素(由于冲突),因此映射到同一个存储桶。 Same key different actual elements. 相同的键不同的实际元素。
So if e.hash != hash you don't need to check for equality (which could be an expensive operation) 所以如果e.hash != hash你不需要检查是否相等(这可能是一个昂贵的操作)

The answer is surprisingly YES. 答案令人惊讶的是。 I put Sysout's in the code of put() to observe it's behaviour 我把Sysout放在put()的代码中来观察它的行为

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. 好奇地试图为此得到答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 hashmap 中具有不同键的相同值 - Same values with different keys in a hashmap 为什么java.util.HashMap中的支持表索引对于两个不同的提供键是相同的? - Why can index of backing table in java.util.HashMap be the same for two different provided keys? 如何将具有相同键的两个 HashMap 中的值(不同数据类型)放入新的第三个 HashMap? - How do I put in the values (of different data types) from two HashMaps with the same keys into a new third HashMap? 如何在具有不同键的外部hashMap中传递具有相同键的内部hashMap? - How to pass an inner hashMap with same keys inside an outer hashMap with different keys? 无论如何在Java HashMap中有两个相同的键,但是值不同? - Anyway to have two of the same keys, but different values in Java HashMap? 当不同的键具有相同的哈希码时,为什么在 HashMap 中没有冲突 - Why is there no collision in a HashMap when different keys have the same hash code 逻辑上相同,但哈希表得到不同的结果 - Logical same but get different result for hashmap 如果键在Java HashMap中包含相同的子字符串,则获取所有值 - Get all values if Keys contain same substring in Java HashMap Java:如何在hashmap中获取具有相同值的键集 - Java: How to get set of keys having same value in hashmap 获取Hashmap前3个键 - Get Hashmap Top 3 Keys
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM