HashMap 解析

HashMap 是由数组+链表/红黑树组成的一种k-v键值对结构。

HashMap 存储数据无序,key 和 value 都可以为 null,key唯一。

HashMap 初始化

在 jdk 1.8 中,HashMap 的构造函数不会创建数组,而是在第一次调用 put() 方法时创建数组,Node[] table 来存储键值对数据。

HashMap 属性

HashMap 默认容量为16。
size HashMap中的元素个数,而不是数组长度。
threshold(临界值) = capacity(容量)* loadFactor(加载因子),size超过临界值就需要扩容。
集合最大容量:1 << 30 2的30次幂
TREEIFY_THRESHOLD = 8; 桶上节点大于这个值且数组长度大于 64 时才会转化红黑树。

HashMap 扩容时,会扩容至2倍。当数组扩容后,索引位置要么是在原索引,要么在原索引+旧数组容量。

HashMap 存储过程

HashMap 进行数据存储时,只计算 key 的 hash 值,根据 key 的 hashcode 来计算路由地址(即在数组中的索引),如果发生 hash 碰撞,使用 key 重写的 equals() 方法与原地址的 key 进行比较,如果相同,则不进行任何操作,如果不相同则插入到原 key 的后面(根据具体情况分析是链表还是红黑树);如果没有发生数据碰撞,就将数据放在数组上。

HashMap 中计算 key hash值的方式

HashMap 底层采用 key 的hashCode 与自己右移 16 位进行按位与运算,保证参与运算的 hash 保存高16位性质。

(h = key.hashCode()) ^ (h >>> 16)

HashMap 路由地址的运算:
其中 n 为数组长度,hash 为 key 计算出的 hash 值。

(n - 1) & hash

构造方法传入数组长度创建 HashMap

如果通过 new 传递的数组长度不是 2 的次幂的话,代码会找到比该值大且最接近该值的2的次幂数设置为数组长度。

该操作会使 n 的二进制最高位往下全部为 1 结束。

int n = cap - 1;
n |= n >>> 1; // ‘|’ 按位或运算,相同位上都为0,才为0
n |= n >>> 2; // ‘>>>’ 无符号右移
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值