参考博客:https://blog.csdn.net/carson_ho/article/details/79373026
参考博客:https://blog.csdn.net/carson_ho/article/details/79373134
一、1.7HashMap数据结构
1.HashMap 采用的数据结构 = 数组 + 单链表
2.每个数组元素和单链表元素值均为键值对
3.HashMap中的数组元素 & 链表节点 采用 Entry类 实现
即 HashMap的本质 = 1个存储Entry类对象的数组 + 多个单链表
Entry对象本质 = 1个映射(键 - 值对),属性包括:键(key)、值(value) & 下1节点( next) = 单链表的指针 = 也是一个Entry对象,用于解决hash冲突
4.主要参数
容量(默认16)、加载因子(默认0.75)、扩容阈值(容量X加载因子)
5.当 key ==null时,将该 key-value 的存储位置规定为数组table 中的第1个位置,即table [0]
6.hashMap发生hash冲突头插法
7.扩容机制:
a.需要扩容新建数组
b.重新计算每个键值对位置
c.将元素转移到新数组上(正向遍历-逆向转移)
d.将新数组引用到Map table上
e.重新设置扩容阈值
A.为什么不直接采用经过hashCode()处理的哈希码 作为 存储数组table的下标位置?
B.为什么采用 哈希码 与运算(&) (数组长度-1) 计算数组下标?
B.为什么在计算数组下标前,需对哈希码进行二次处理:扰动处理?
在回答这3个问题前,请大家记住一个核心思想:
所有处理的根本目的,都是为了提高 存储key-value的数组下标位置 的随机性 & 分布均匀性,尽量避免出现hash值冲突。即:对于不同key,存储的数组下标位置要尽可能不一样
二、1.8HashMap数据结构
1.HashMap 采用的数据结构 = 数组 + 单链表+红黑树
(单个链表长度>8 存储在红黑树)
2.HashMap中的数组元素 & 链表节点 采用 node类 实现
HashMap中的红黑树节点 采用 TreeNode 类 实现
3.主要参数
容量(默认16)、加载因子(默认0.75)、扩容阈值(容量X加载因子)、红黑树相关的参数
4.hashMap发生hash冲突红黑树尾插法
5.扩容机制:
a.需要扩容新建数组
b.遍历就数组的每个数据
c.重新计算每个键值对位置(原位置or原位置+旧容量)
d.将元素转移到新数组上(头插法)
e.将新数组引用到Map table上
f.重新设置扩容阈值
2.存储流程