【问题标题】:Calculating hashcode of the key twice in HASHMAP [duplicate]在 HASHMAP 中两次计算密钥的哈希码 [重复]
【发布时间】:2015-08-21 19:59:32
【问题描述】:

我一直在研究Hashmap 实现的内部结构。

对于基于键从映射中添加或获取值,它将计算哈希码,然后找到存储桶位置(或表位置/索引,如果我错了,请纠正我)。
但它计算了两次哈希码。

在下面的代码sn-p中,key.hashcode()是对象类中的native方法,然后hash方法在同一个类中实现。
在 hash 方法的 cmets 中给出了为什么要计算两次,我无法理解。

谁能用一个场景简单解释一下?

int hash = hash(key.hashCode());

/ * Applies a supplemental hash function to a given hashCode, which
* defends against poor quality hash functions.  This is critical
* because HashMap uses power-of-two length hash tables, that
* otherwise encounter collisions for hashCodes that do not differ
* in lower bits. Note: Null keys always map to hash 0, thus index 0.           
*/
static int hash(int h) {
    // 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);
}

谢谢。

【问题讨论】:

    标签: java


    【解决方案1】:

    http://tekmarathon.com/2012/12/04/hashmap-internal-implementation-analysis-in-java/

    这意味着如果我们为生成哈希码而编写的算法没有均匀地分配/混合低位,则会导致更多的冲突。例如,我们有“empId*deptId”的哈希码逻辑,如果deptId 是偶数,它总是会生成偶数哈希码,因为任何数字乘以偶数总是偶数。如果我们直接依赖这些哈希码来计算索引并将我们的对象存储到哈希图中,那么 1. hashmap中奇数的地方总是空的 2. 因为#1,它会让我们只使用偶数的地方,因此碰撞次数增加一倍

    它可以防止写得不好的散列函数。此外,即使它们不一定相同,类似值的对象也可能导致冲突。冲突不好,它们增加了查找与键关联的值的时间,因为每个散列指向一个值的链表,必须在检索时迭代以匹配正确的键。即使具有良好的哈希函数,您仍然需要“混合低位”以确保两个分布的均匀幂。

    另请参阅:

    免责声明:我与 HashMaps 密切合作一年多,这是所有研究的来源

    【讨论】:

    • 表和桶是一样的吗?,这个术语我见过很多次,所以只需要确认。
    • 解释得很清楚,所以我们重写了hascode方法,实现很差,允许更多的冲突,然后它防御它。如果我们不重写它,实际的hashcode(内存地址的整数equivlanet对象)不是一个糟糕的实现(我认为),所以在那种情况下额外的开销对吗?
    • 1) 取决于上下文。表通常表示散列表或基于键/值对散列的集合。桶是哈希表(HashMap)的每个索引,之所以这样命名,是因为它们可以关联许多有哈希冲突的键值对。 2)hashCode的默认Java实现,当然是不完善的。第二个散列确保 hashCode() 的位充分混合以适应表的两个长度的幂。它还确保了未很好实现的覆盖 hashCode() 的均匀分布。
    • 实际上,当我签入 java 文档时,具有变量名称的存储桶被声明为表。瞬态条目[]表;表=新条目[默认容量];而Entry对象定义为 --> Entry(int h, K k, V v, Entry n) { value = v;下一个 = n;键=k;哈希 = h; }. 变量名称表让我有点困惑,因为我们通常称它为存储桶。如果我错了,请纠正我
    • 每个条目都被称为桶,因为它们拥有重复的哈希键。该表是桶的集合。
    猜你喜欢
    • 2013-08-28
    • 1970-01-01
    • 1970-01-01
    • 2012-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-21
    相关资源
    最近更新 更多