为啥HashMap的容量为什么要是2的n次方

引入

我们知道,hash方法的功能是根据Key来定位这个K-V在链表数组中的位置的。也就是hash方法的输入应该是个Object类型的Key,输出应该是个int类型的数组下标。如果让你设计这个方法,你会怎么做?

其实简单,我们只要调用Object对象的hashCode()方法,该方法会返回一个整数,然后用这个数对HashMap的容量进行取模就行了。

如果真的是这么简单的话,那HashMap的容量设置就会简单很多了,但是考虑到效率等问题,HashMap的hash方法实现还是有一定的复杂的。

hash的实现

主要涉及到两个部分:
1.计算hash

    //该方法主要是将Object转换成一个整型。
    //>>>无符号右移
    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

这里为什么要右移16位呢?
因为这个方法计算出来的hash值,到后面需要和数组的长度tab.length进行&运算,但由于绝大多数情况下length一般都小于2^16即小于65536。所以h & (length-1);结果始终是h的低16位与(length-1)进行&运算。要是高16位也参与运算,会让得到的下标更加散列。所以这里做了一个
h = key.hashCode()) ^ (h >>> 16);
让他重新生成新的hash,减少hash冲突
2.将hash生成的整型转换成链表数组中的下标

n = tab.length
p = tab[i = (n - 1) & hash]

这里其实就是求模的操作,当length是2的n次方的时候hash%length==hash&(length-1)等价,这里也解释了为什么hashmap的容量一定是2的n次方

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值