HashMap底层数据结构分析

1.HashMap 的底层是数组

// 参考代码
HashMap<String, String> map = new HashMap<String, String>();
map.push("张三","测试数据1");
map.push("李四","测试数据2");

// 底层的数据类型简单展示,当然实际上远远没有这么简单,这里是方便理解
[<张三, 测试数据1>, <李四, 测试数据2>]

2.底层原理

1. 首先会根据'张三'这个 key 计算出它的 Hash 值;

2. 拿到 Hash 值对数组的长度进行取模(数组是有固定长度的),定位到将要存入的数组中的指定位置;
   [<>, <>, <>, <>, <张三, 测试数据1>, <>, <李四, 测试数据2>, <>]

3. 取值原理也是先计算处 Hash 值后进行取模,拿到指定下标获取元素;

4. 实际上 JDK 中 HashMap 的原理要比以上的逻辑复杂一些,还有一些防止 Hash 重复,数组扩容的操作等等;

3.JDK 1.8中对Hash算法和寻址算法的优化

// 代码示例
map.push("张三", "测试数据");

// 1.在 JDK 1.8 中对 “张三” 这个 key 计算 Hash 值是有一定的优化的
static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (key.hashCode())^(h >>> 16);
}

// 比如说: 存在一个 key 的 hash 值
// 1111 1111 1111 1111 1111 1010 0111 1100
// 右移16位(h >>> 16):
// 0000 0000 0000 0000 1111 1111 1111 1111
// 将两个 hash 进行异或运算(对比是否一样)得出新的 hash 值:
// 1111 1111 1111 1111 0000 0101 1000 0011
// 将转换后的异或 hash(32位) 值转int(32位)进行返回;

// 2. 寻址算法优化: n 数组长度
(n -1) & hash

// 假设数组的长度为 16 位,(n -1) & hash 算出的 hash 值如下:
// 0000 0000 0000 0000 0000 0000 0000 1111
// 没有经过优化 key 的 Hash 值如下:
// 1111 1111 1111 1111 1111 1010 0111 1100
// 优化后的新 hash 值:
// 1111 1111 1111 1111 0000 0101 1000 0011
// 取模的运算性能比较差,(n -1) & hash 运算的效果和取模是一样的, 但是性能比取模高的多;
// 如果使用没有优化过的 hash 值进行 & 运算,两个值的区别很小,容易出现多个 key 算出的位置是一样的情况,因此要进行异或运算

4.总结

1.Hash 算法的优化: 对每个 hash 值,在他的低 16 位中, 让他的高低 16 位都进行异或运算, 让他的低 16 位同时保持了 高 16 位的特征,尽量避免了一些 hash 值后续出现的冲突,即多个不同的 key 存入同一个数组位置;

2. 寻址算法的优化: 用 & 运算代替了取模运算,提高了运算的性能;

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值