HashMap哈希函数-二进制运算符

Dee*_*mar 1 java hash hashmap hash-collision java-8

我正在查看HashMap的源代码,但是二进制运算符使很多人感到困惑。

我确实了解以下的一般目的,公平分配并将hashCode限制在存储桶限制之内。

有人可以在这里解释评论吗?立即进行操作有什么好处?

/**
     * Computes key.hashCode() and spreads (XORs) higher bits of hash
     * to lower.  Because the table uses power-of-two masking, sets of
     * hashes that vary only in bits above the current mask will
     * always collide. (Among known examples are sets of Float keys
     * holding consecutive whole numbers in small tables.)  So we
     * apply a transform that spreads the impact of higher bits
     * downward. There is a tradeoff between speed, utility, and
     * quality of bit-spreading. Because many common sets of hashes
     * are already reasonably distributed (so don't benefit from
     * spreading), and because we use trees to handle large sets of
     * collisions in bins, we just XOR some shifted bits in the
     * cheapest possible way to reduce systematic lossage, as well as
     * to incorporate impact of the highest bits that would otherwise
     * never be used in index calculations because of table bounds.
     */
    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }
Run Code Online (Sandbox Code Playgroud)

如果有人可以帮助我理解它,那将是一个很大的帮助。

这不是重复的,因为其他问题与Java 8之前的哈希实现有关。

提前致谢

NPE*_*NPE 5

hashCode()返回int32位宽的。

在内部,HashMap将物体放在pow(2, n) 箱中。的值n可能会有所不同-此处的细节并不重要;重要的n是通常比32(哈希中的位数)小得多。

每个对象都放在一个存储桶中。为了获得良好的性能,期望将物体均匀地分布在铲斗上。这就是对象哈希值出现的地方:选择存储桶的最简单方法是采用n对象哈希码的最低位(使用简单的按位与)。但是,这只会使用最低的n位,而忽略其余的哈希。

在评论中,作者认为这是不可取的。他们列举了一些已知用例的示例,在这些用例中,对象散列除最低位外在位上系统地不同n。这将导致系统性冲突,而系统性冲突则是个坏消息。

为了部分解决此问题,他们实施了当前的启发式方法:

  • 保持哈希的前16位不变;
  • 用高16位和低16位的XOR替换低16位。