为什么ConcurrentHashMap在1.8中使用0x7fffffff计算哈希码?

时间:2018-05-30 15:16:34

标签: java hashcode concurrenthashmap

何时计算密钥的哈希码,调用spread()方法:

static final int spread(int h) {
    return (h ^ (h >>> 16)) & HASH_BITS;
}

HASH_BITS等于0x7fffffff,那么HASH_BITS的目的是什么?有人说它使符号位为0,我不确定。

2 个答案:

答案 0 :(得分:2)

散列桶中的KV节点的index通过以下公式计算:

index = (n - 1) & hash
  • hashspread()
  • 的结果
  • n是散列桶的长度,最大值为2 ^ 30

    private static final int MAXIMUM_CAPACITY = 1 << 30;

因此n - 1的最大值为2 ^ 30 - 1,这意味着hash的最高位将永远不会用于索引计算。

但我仍然不明白是否有必要将hash的最高位清除为0.似乎有更多理由这样做。

/**
 * Spreads (XORs) higher bits of hash to lower and also forces top
 * bit to 0. 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 spread(int h) {
    return (h ^ (h >>> 16)) & HASH_BITS;
}

答案 1 :(得分:1)

我认为这是为了避免与保留的哈希码冲突:MOVED(-1),TREEBIN(-2)和RESERVED(-3)的符号位始终为1。