Java基础——HashMap

一、初始化HashMap实例

 赋值负载因子——扩容的阀值
默认四分之三

二、第一次新增元素

1)put()方法

hash(key)    

2)hash(key)方法

key.hashCode()

3)查看整型Integer和字符串String类型的hashCode()

字符串类型的hashCode()
整型的hashCode()

4)回到hash()方法,使用扰动函数重新计算哈希值


0^0=0,0^1=1,1^1=0

5)扰动函数图解

扰动函数让哈希值更平均

6)putVal()方法

方法较长,需要一步一步解析

7)putVal()方法,进入第一个If判断

将全局变量table赋值给局部变量tab
首次添加元素哈希桶为空

8)resize()方法

扩容部分
数据迁移部分
初始化局部变量oldTab为旧数组,oldCap为旧数组容量,oldThr为旧数组扩展阈值
threshold=capacity * load factor

9)resize()扩容部分

执行红框内容


由此可见newCap被赋值16,而newThr被赋值为16*0.75=12

10)resize()数据迁移部分——首次添加元素由于无旧数据不执行

遍历旧数组,一边清空一边迁移

jdk1.8之前hashMap多线程产生死锁,jdk1.8之后不会的原因?

jdk1.8之后链表使用尾插法,jdk1.8之前使用头插法(就是新元素添加到链表头部还是链表尾部)

树结构迁移
链表结构迁移

11)putVal()方法,进入第二个If判断

1&1=1,1&0=0,0&0=0
无哈希冲突,直接新建Node节点复制给数组

12)哈希寻址冲突

p在判断时被赋值为产生冲突的节点值

13)key值相同——红黑树中也会有key值相同

将p赋值给e,插入新value

14)红黑树处理哈希冲突

红黑树必备的五大条件?

条件一:所有节点要么是红节点,要么是黑节点

条件二:根节点必定是黑节点

条件三:红节点的左右子节点都是黑节点

条件四:所有叶子节点都是黑节点(要么是有值的黑节点,要么为空的黑节点)

条件五:从任意一个节点到叶子节点,经过的黑节点都一样多

putTreeVal()
上半部负责跳出循环,下半部变色旋转操作
仅变色
变色+旋转

15)链表处理哈希冲突

HashMap链表什么时候转红黑树?

在 binCount>=TREEIFY_THRESHOLD-1(第八次寻找链表节点),并且大于等于MIN_TREEIFY_CAPACITY(数组长度大于等于64)的时候。  


16)链表转红黑树方法treeifyBin()

17)putVal()最后一部分

三、查找元素

树结构先找到root

你可能感兴趣的:(Java基础——HashMap)