HashMap.resize() 上 对容量,阈值的调整

  1. 没有考虑树的情况,只考虑链表的情况
  2. 建议先自己看一下resize源码,琢磨之后再来看博客
  3. 这个方法中包含了对哈希表的扩容(或者初始化),把原来哈希表中的元素搬到新哈希表中去,把原来链表上的各个元素也搬到新的哈希表去
Node<K,V>[] oldTab = table;
// 拿到原来的哈希表,原来的哈希表长度就是旧容量
int oldCap = (oldTab == null) ? 0 : oldTab.length;
// 拿到原来的阈值
int oldThr = threshold;
// 定义新容量,新阈值为0
int newCap, newThr = 0;
// 当旧容量不为0的时候
// 这里要注意,当new 一个hashmap对象的时候,并不会马上初始化哈希表,但是会初始化阈值(会变成2的N次方),详见java.util.HashMap#HashMap(int, float)
// 在put的时候会进行resize,但第一次resize,也就是第一次put的时候,旧容量是0,
// 也就是说,当旧容量大于0的时候,也就不是第一次put的时候了
if (oldCap > 0) {
    // 需要注意 MAXIMUM_CAPACITY = 1 << 30 等于 2的30次方,因为哈希表的长度要是2的N次方
    // 当容量等于MAXIMUM_CAPACITY的时候说明容量已经不能再继续增加了
    if (oldCap >= MAXIMUM_CAPACITY) {
        // 这是将阈值设置为最大,就算到了这个阈值也不做什么了,不扩容,将原来的哈希表返回
        threshold = Integer.MAX_VALUE;
        return oldTab;
    }
    // 这一步有点难理解
    // 先将旧容量变成原来的两倍
    // 1、因为当旧容量大于等于最大值的时候,阈值是要赋值为最大值的,这里的操作是要把阈值变为原来的两倍。所以旧容量变成原来的两倍之后,不能大于等于MAXIMUM_CAPACITY
    // 当大于等于最大容量的时候,在下面进行赋值,不会说这次先不管阈值
    // 2、为什么要扩容后的容量大于等于16呢? 
    // 如果一开始指定容量是2,那么阈值就是(int)(1*0.75),也就是1
    // 在进行扩容之后,新容量变成4,这时如果对就阈值乘以两倍的话,新阈值就是2,那么负载因子就变成了0.5,而不是0.75了
    // 也就是因为在容量小的时候,容量乘以负载因子存在误差,这个存在误差的值不能跟着容量的变大而变大,不然误差会越来越大
    // 在容量小的时候,扩容后应该重新计算阈值
    else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
             oldCap >= DEFAULT_INITIAL_CAPACITY)
        newThr = oldThr << 1; // double threshold
}
// 到这里,说明是第一次resize,因为容量为0,阈值在构造的时候指定了,将新容量设置为阈值
else if (oldThr > 0) // initial capacity was placed in threshold
    newCap = oldThr;
// 到这里,说明是第一次resize,并且构造的时候没有指定容量和阈值,将新容量和新阈值设置为默认的
else {               // zero initial threshold signifies using defaults
    newCap = DEFAULT_INITIAL_CAPACITY;
    newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
}
// 到这里,说明以上的种种都没有成功对新阈值进行赋值
// 1、不是第一次resize,因为第一次resize的时候肯定会对新阈值进行赋值的
// 2、不是第一次resize,并且扩容后的容量小于16,也就是阈值需要有容量乘以负载因子算出来,而不是刻意将原来的的阈值翻倍
if (newThr == 0) {
    float ft = (float)newCap * loadFactor;
    newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
              (int)ft : Integer.MAX_VALUE);
}
threshold = newThr;
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值