聊一聊HashMap的巧妙算法

99 阅读1分钟

tableSizeFor

tableSizeFor算法是为了得到第一个大于等于给定整数的2的整数次幂

源码如下

static final int tableSizeFor(int cap) {
    int n = cap - 1;
    n |= n >>> 1;
    n |= n >>> 2;
    n |= n >>> 4;
    n |= n >>> 8;
    n |= n >>> 16;
    return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}

找到最高位的1,则n的二进制表示为1xxxx

n |= n >>> 1,最高位有连续两个1

n |= n >>> 2,最高位有连续四个1

以此类推,n >>> 16,所有位都是1

再对n+1,就得到了2的整数次幂

cap本身已经是2的n次幂的情况下,这样算出来会是2*cap,所以需要先对cap减一

hash

用hash方法求出key的hash值,再对size取模得到数组下标

源码如下

static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

hash算法之所以要对hashCode右移16位再异或,是因为在对size取模时,可能用不到hashCode的高位信息,这样数组下标冲突的概率就会比较大。对hashCode右移16位再异或,相当于在低位也糅合了高位的信息,减少了取模后发生冲突的概率