为什么我们需要检查两次哈希码?
Why do we need to check hashcode twice?
这是 HashMap.java (docjar) 的代码。键的哈希值在第 431 行计算。这有助于在第 432 行获取索引 i。该索引处的所有条目都应具有相同的哈希值。为什么要在第 440 行再次检查散列相等性? (if (e.hash == hash )
private void putForCreate(K key, V value) {
430 int hash = (key == null) ? 0 : hash(key.hashCode());
431 int i = indexFor(hash, table.length);
432
433 /**
434 * Look for preexisting entry for key. This will never happen for
435 * clone or deserialize. It will only happen for construction if the
436 * input Map is a sorted map whose ordering is inconsistent w/ equals.
437 */
438 for (Entry<K,V> e = table[i]; e != null; e = e.next) {
439 Object k;
440 if (e.hash == hash &&
441 ((k = e.key) == key || (key != null && key.equals(k)))) {
442 e.value = value;
443 return;
444 }
445 }
446
447 createEntry(hash, key, value, i);
448 }
同一个桶可能包含其键具有不同哈希码的条目(因为桶索引 i
是通过对计算的哈希应用模数 table.length
确定的,因此不同的哈希码可能映射到相同的存储桶),因此第 440 行中的比较使您无需为两个不具有相同哈希码的键调用 equals
,这通常比比较两个 int
更昂贵s.
这是 HashMap.java (docjar) 的代码。键的哈希值在第 431 行计算。这有助于在第 432 行获取索引 i。该索引处的所有条目都应具有相同的哈希值。为什么要在第 440 行再次检查散列相等性? (if (e.hash == hash )
private void putForCreate(K key, V value) {
430 int hash = (key == null) ? 0 : hash(key.hashCode());
431 int i = indexFor(hash, table.length);
432
433 /**
434 * Look for preexisting entry for key. This will never happen for
435 * clone or deserialize. It will only happen for construction if the
436 * input Map is a sorted map whose ordering is inconsistent w/ equals.
437 */
438 for (Entry<K,V> e = table[i]; e != null; e = e.next) {
439 Object k;
440 if (e.hash == hash &&
441 ((k = e.key) == key || (key != null && key.equals(k)))) {
442 e.value = value;
443 return;
444 }
445 }
446
447 createEntry(hash, key, value, i);
448 }
同一个桶可能包含其键具有不同哈希码的条目(因为桶索引 i
是通过对计算的哈希应用模数 table.length
确定的,因此不同的哈希码可能映射到相同的存储桶),因此第 440 行中的比较使您无需为两个不具有相同哈希码的键调用 equals
,这通常比比较两个 int
更昂贵s.