HashMap容量是2的幂次方有什么用

一、将取模运算转成按位与运算

HashMap需要计算散列位置,通常的做法是取模,即X % 2^n(X即为准备放入HashMap中的key)。取模运算的逻辑一般为两步,第一步求商,即c = a/b;第二步求余数,即r = a-c*b。这两步包含了除法,乘法和减法运算。有一种情况,当容量为2的幂次方时,可以将取模运算转成按位与运算。该转换满足这样的等式:X % 2^n = X & (2^n - 1)。计算机中,除法、乘法和减法都可以转换成加法运算,而加法运算可以通过与或非门实现。从而可以看出取模运算到与(非或)运算有很多步转换,性能自然是取模运算差。我们把取模运算转成按位与运算,可以提高计算散列位置的性能。而转换的前提就是需要满足容量是2的幂次方

二、扩容时的rehash

HashMap在扩容时,会扩容成原来容量的2倍。如果满足容量为2的幂次方,扩容之后在重新计算散列位置时,可以通过判断有效位的最高为是1还是0,而确定该元素应该放到低位(假设扩容之前的容量为低位,扩容之后的新容量为高位)还是高位,在HashMap的resize方法中有下面的一段代码

                        Node<K,V> loHead = null, loTail = null;
                        Node<K,V> hiHead = null, hiTail = null;
                        Node<K,V> next;
                        do {
                            next = e.next;
                            if ((e.hash & oldCap) == 0) {
                                if (loTail == null)
                                    loHead = e;
                                else
                                    loTail.next = e;
                                loTail = e;
                            }
                            else {
                                if (hiTail == null)
                                    hiHead = e;
                                else
                                    hiTail.next = e;
                                hiTail = e;
                            }
                        } while ((e = next) != null);
                        if (loTail != null) {
                            loTail.next = null;
                            newTab[j] = loHead;
                        }
                        if (hiTail != null) {
                            hiTail.next = null;
                            newTab[j + oldCap] = hiHead;
                        }

当元素的hash值与旧容量(注意此时没有减1)进行按位与运算得出的结果为0,即放到低位,也就是loHead,loTail中;当运算得到的是1,即放到高位,也就是hiHead,hiTail中。低位的loHead和loTail放的桶位置不变,高位的loHead和loTail放的桶位置变成原索引+旧容量。

举例来说,假设有两个key,key1的hash是10001,key2的hash是00001。当前HashMap容量为16。对key1、key2跟16-1也就是1111进行与运算时,两个key都放到了1这个桶中。当完成扩容后,当前HashMap容量为32。对key1、key2跟32-1也就是11111进行与运算时,key1应该放到17这个桶中,也就是1+16,原来的桶索引+旧容量;key2还放在原来的桶中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值