HashMap源码分析

在这里插入图片描述
Entry 存储着键值对。它包含了四个字段,从 next 字段我们可以看出 Entry 是一个链表。即数组中的每个位置被当成一个桶,一个桶存放一个链表。HashMap 使用拉链法来解决冲突,同一个链表中存放哈希值相同的 Entry
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2. 拉链法的工作原理
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
HashMap 允许插入键为 null 的键值对。但是因为无法调用 null 的 hashCode() 方法,也就无法确定该键值对的桶下标,只能通过强制指定一个桶下标来存放。HashMap 使用第 0 个桶存放键为 null 的键值对。
(解释:下图代码中,首先把第0个桶的地址赋给e,然后判断这个桶的第一个Entry的key是否等于null,如果等于null,那么就用新值来覆盖旧值,然后把旧值作为函数的返回结果,然后依次遍历第0个桶的各个Entry,如果遍历完了都没有一个key等于null,说明我们要在第0个桶上新添一个key==null的元素,然后把函数参数value作为key对应的值)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
小疑问:二进制数之间取模是怎么运算来着?
我们知道,位运算的代价比求模运算小的多,因此在进行这种计算时用位运算的话能带来更高的性能。

确定桶下标的最后一步是将 key 的 hash 值对桶个数取模:hash%capacity,如果能保证 capacity 为 2 的 n 次方,那么就可以将这个操作转换为位运算。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
从下面的添加元素代码中可以看出,当需要扩容时,令 capacity 为原来的两倍。(解释:不要和上面的threshold,loadFactor这两个参数搞绕了,这两个参数只是决定了当存储元素达到多少的时候扩容,而不是决定要扩容的倍数)
在这里插入图片描述
扩容使用 resize() 实现,需要注意的是,扩容操作同样需要把 oldTable 的所有键值对重新插入 newTable 中,因此这一步是很费时的。
在这里插入图片描述
在这里插入图片描述
解释: 因为y%x的结果和y&&(x-1)的结果相等,所以上述图中capacity-1=00001111,new capacity-1=00011111,所以如果一个key的hash值在第5位上为0,那么取模得到的结果和之前是一样的,如果为1,那么得到的结果为原来的结果+16
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java全栈研发大联盟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值