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