HashMap 1.7 与 1.8的区别

HashMap 1.7 与 1.8的区别
1.7版本: HashMap是一个数组+链表的结构来存储数据。我们可以初始化HashMap的大小,初始化的值为大于0 小于等于1<<30直接的任意值。因为是数组+链表结构,所以一个10Capacity的HashMap可以装入大于10的个对象。当装入对象时,用以下方式判断是否扩容。
// size: 当前加入对象数量
// threshold: 当前容器数组的长度
// table: 容器数组
// bucketIndex: 准备添加到容器的对象的索引
if((size >= threshold) && (null != table[bucketIndex])){
扩容2倍
}
扩容后,每一个节点的索引位置都需要重新计算hash来确定。这样就是一个比较大的计算量。

1.8版本:HashMap的结构中增加了红黑树结构。在加入对象时,首先通过对象的hash计算索引值,如果在容器数组中该索引为空,直接加进去,如果该位置不为空,该位置将变为一个链表。如果这个链表的长度到达8个,这个链表将变成一个树。每一个添加到容器的对象都会封装成一个Node,Node中有next等链表属性。
第二个区别,用户指定初始容器大小时,容器只会被初始化为2的N次方。 比如我们输入5来初始化容器大小,容器的真实初始化大小会为8。容器的大小只能是2的N次方。这种规定对容器扩容节点重新计算位置有很大帮助。
对于扩容时重新计算节点位置的算法:
当添加对象节点时,到达容器扩容条件,需要扩容。扩容后将导致每个节点的位置将发生变化。在重新计算节点位置上1.8比1.7有优化。优化方案是节点的 hash值&原容量值 如果为0,该节点在新容器中的位置不发生变化;如果不为0,该节点的位置将向后偏移原容量值位。比如一个容器原始容量为16,Node1在扩容前索引为1,容器扩容后,如果Node1的hash&16大于0,那么Node1的新索引为1+16。

A - 16 的二进制 B ---- 16-1 15的二进制
0000 0000 0000 0000 0000 0000 0001 0000 0000 0000 0000 0000 0000 0000 0000 1111
xxxx xxxx xxxx xxxx xxxx xxxx xxxy 1010 xxxx xxxx xxxx xxxx xxxx xxxx xxxy 1010 B组做&运算的结构是在16大小的容器中的位置。

C — 32的二进制 D ----- 32-1 31的二进制
0000 0000 0000 0000 0000 0000 0010 0000 0000 0000 0000 0000 0000 0000 0001 1111
xxxx xxxx xxxx xxxx xxxx xxxx xxxy 1010 xxxx xxxx xxxx xxxx xxxx xxxx xxxy 1010 D组做的&运算结果为该节点在32大小容器中的位置。

A组的&运算结果只与y这位值有关系, 如果y为0,那么结果为0,如果y为1,那么结果是非0。为何步计算关系该节点是否改变位置,请看D的运算,如果y为1,那么B和D的运算结果将不同,而且正好相差16(其实就是一个高位)。如果y为0,那么B和D的运算结果就相同,位置就不变。
用上面的例子通俗来讲,如果在16的容器里,每个节点的hash值只需要由低到高前4位参数运算。当然扩容后,每个节点的hash值将需要由低到高前5参与运算。如果第5位为0,位置不变,如果第5位为1,位置偏移16。

该算法在1.8hashMap扩容里,用在树的裁剪和链表修改上, 比如一个节点时一个链表,会遍历链表中的节点,计算每个节点的位置是否需要改变,不改变位置的节点形成链表loHead,要改变位置的节点形成链表hiHead。loHead还是在原来的索引位置,hiHead到新的索引位置。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值