当前位置: 首页 > 面试题库 >

HashMap#hash(int)方法的说明

松新
2023-03-14
问题内容

有人可以向我解释静态HashMap#hash(int)方法吗?

产生均匀分布的哈希的背后的理由是什么?

/**
 * 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);
}

一个例子将使它更容易消化。

澄清 我知道运算符,真值表和按位运算。我只是无法真正解码实现,也无法真正评论。甚至是背后的原因。


问题答案:

>>>是逻辑右移(无符号扩展)(JLS 15.19 Shift
Operators
),并且^是按位异或(JLS
15.22.1 Integer Bitwise
Operators

)。

关于这样做的原因,文档提供了一个提示:HashMap使用2的幂的长度表,并通过掩盖掉哈希码的较高位并仅获取其较低位来哈希键。

// HashMap.java -- edited for conciseness
static int indexFor(int h, int length) {
    return h & (length-1);
}

public V put(K key, V value) {
    int hash = hash(key.hashCode());
    int index = indexFor(hash, table.length);
    // ...
}

因此,hash()尝试使相关性与较高的位有关,否则将被屏蔽掉(indexFor基本上丢弃的较高位,h而仅在处使用较低的klength == (1 << k))。

将此与Hashtable使用密钥的哈希码的方式(应该没有二乘幂长度表)进行对比。

// Hashtable.java -- edited for conciseness
public synchronized V get(Object key) {
    int hash = key.hashCode();
    int index = (hash & 0x7FFFFFFF) % table.length;
    // ...
}

通过执行更昂贵的%操作(而不是简单的位屏蔽),的性能Hashtable在较低位(尤其table.length是素数)中分布较差的哈希码不太敏感。



 类似资料:
  • 问题内容: 谁能详细解释这种方法,谢谢。 问题答案: 设计通用哈希码的问题之一是,您将所有这些工作都放在了确保良好的位扩展上,然后有人来使用并以完全撤消的方式使用它。 让我们以一个带有X和Y(均为整数)的坐标类的经典示例为例。 这是一个经典的示例,因为人们会用它来证明这不是一个很好的哈希码,因为通常会有多个对象,其中(所有哈希都为0)或X和Y为Y和X的对象其他(将散列相同)和其他情况下,我们最终得

  • 本文向大家介绍请你说一下解决hash冲突的方法?相关面试题,主要包含被问及请你说一下解决hash冲突的方法?时的应答技巧和注意事项,需要的朋友参考一下 参考回答: 当哈希表关键字集合很大时,关键字值不同的元素可能会映象到哈希表的同一地址上,这样的现象称为哈希冲突。目前常用的解决哈希冲突的方法如下: 开放定址法: 当发生地址冲突时,按照某种方法继续探测哈希表中的其他存储单元,直到找到空位置为止。 再

  • 我试图用这个键得到一个值。我正在使用get()方法。我的密钥是由int和String组成的对象。所以我提出反对 我收到了空的。当我查看去bug模式或打印密钥集时,我收到类似的消息 虽然我的钥匙应该是 为什么键看起来像这样而不是以及如何使用键获取值? 我在键中覆盖了字符串methid。它看起来更好,但我仍然有空值,我相信有一些价值。

  • 本文向大家介绍Java ArrayList add(int index, E element)和set(int index, E element)两个方法的说明,包括了Java ArrayList add(int index, E element)和set(int index, E element)两个方法的说明的使用技巧和注意事项,需要的朋友参考一下 一般使用List集合,估计都是使用这个Arr

  • 本文向大家介绍js数组去重的hash方法,包括了js数组去重的hash方法的使用技巧和注意事项,需要的朋友参考一下 对于 JavaScript 数组去除重复项,现在有多种方法,其中一种是hash,如下: 但是该方法并不严谨,无法区分数字 1 和 字符串 '1' 修改一下,加上数据类型判断: 至少现在对5种原始数据类型的值可以准确去重了,对某些引用类型的值──数组,函数,也可以,但是对象类型──{"

  • 本文向大家介绍Hash表处理冲突的方法相关面试题,主要包含被问及Hash表处理冲突的方法时的应答技巧和注意事项,需要的朋友参考一下 参考回答: 开放定址法 为产生冲突的地址求得一个地址序列(),其中。其中m为表的长度,而增量有三种取值方法,线性探测再散列,平方探测再散列,随即探测再散列。 链地址法 将所有Hash地址相同的记录都链接在同一链表中 再Hash法 同时构造多个不同的Hash函数,当产生