hashmap是真的需要静下心来仔细看看的
1、核心的几个结构
static final float DEFAULT_LOAD_FACTOR = 0.75f; //加载因子,基于空间和查询的综合考虑
static final int TREEIFY_THRESHOLD = 8; //链表转换为红黑树的条件之一
static final int UNTREEIFY_THRESHOLD = 6; //红黑树退化为链表的条件
static final int MIN_TREEIFY_CAPACITY = 64;//链表转换为红黑树的条件,小于此参数进行resize操作
transient Node<K,V>[] table; // 数组结构 transient int size; //hashmap中元素的个数
transient int modCount; //修改次数,fast-fail 的实现基于这个变量
final float loadFactor; //加载因子,新增这个变量减少hash碰撞
Node节点的数据结构如下
Node{
T t;
Node prev;
Node next;
}2、核心的方法
2.1、putVal
可能存在的问题:
- put操作时,tab[index]不存在
- put操作时,key值重复,覆盖 or 直接返回
- put操作时,put的是红黑树
- put节点时,put的是链表,这是需要考虑是否进行
2.2、getNode
设计流程
3、常见问题:
3.1、resize时机?
主要在三个方面
- 数组为0的时候的进行初始化,默认的table.length为16
- 数组的容量超过threshold,进行扩容,原长度<<1
- 链表的长度超过treeifbin变量(默认为8),且小于MIN_TREEIFY_CAPACITY(默认64)
3.2、为啥resize 必须为2的n次方?
原因如下:
- hash % (2<<i -1)的值刚好对应数组下标,对2的n次幂求余有这种性质
- resize的时候移动的元素相对会减少,resize的时候只多增加了一位