【校招VIP】HashMap 1.7和1.8的区别

08月04日 收藏 0 评论 0 java开发

【校招VIP】HashMap 1.7和1.8的区别

转载声明:文章来源:https://blog.csdn.net/m0_62286364/article/details/126130219

HashMap 1.7和1.8的区别

底层结构

底层结构为 数组 + 链表

底层数组为 entry 数组 加载方式类似于单例模式的饿汉式 当new HashMap() 的时候就将数组初始化完成。

底层结构为 数组 + 链表 + 红黑树

底层数组为 Node 数组 加载方式类似于单例模式的懒汉式 当首次执行put操作时会判断数组是否存在,如果不存在将执行resize()方法进行初始化

//将链表转化为红黑树的阀值
static final int TREEIFY_THRESHOLD = 8;

//将红黑树转回为链表的阀值
static final int UNTREEIFY_THRESHOLD = 6;

//将链表转为红黑树的最小entry数组的长度为 64
static final int MIN_TREEIFY_CAPACITY = 64;

当链表的长度 > 8,且entry数组的长度>= 64时,才会将链表转为红黑树。

bitCount初始值为0 所以 >= TREEIFY_THRESHOLD - 1 即为 >= 8

在判断前会执行 p.next = newNode(hash, key, value, null); 增加一个新节点

所以最后的判断条件为 链表长度 > 8

//此处遍历链表
for (int binCount = 0; ; ++binCount) {
//遍历到链表最后一个节点
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
//如果链表元素个数大于等于TREEIFY_THRESHOLD - 1
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
//红黑树转换逻辑
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}

执行put操作

1.7: 头插法 后来的值被查找的可能性更大一点,提升查找的效率。但是当数组扩容时会存在 环形链表 问题。

1.8: 尾插法 解决环形链表问题

环形链表

A->B->C 当扩容后 A、B还是在同一个位置,A先添加后,B再添加,头插法。所以会出现B->A->B的环形链表

扩容时

1.7:是通过更改hashSeed值修改节点的hash值从而达到rehash时的链表分散。 插入数据之前扩容

1.8:键的hash值不会改变,rehash时根据(hash&oldCap)==0将链表分散。 插入数据成功之后扩容

Key 为 NULL

1.8中没有区分键为null的情况,而1.7版本中对于键为null的情况调用putForNullKey()方法。但是两个版本中如果键为null,那么调用hash()方法得到的都将是0,所以键为null的元素都始终位于哈希表table【0】中。

个版本中如果键为null,那么调用hash()方法得到的都将是0,所以键为null的元素都始终位于哈希表table【0】中。

C 0条回复 评论

帖子还没人回复快来抢沙发