开课吧孤尽T31训练营学习笔记-DAY16-HashMap源码解析

176 阅读2分钟

HashMap源码解析

之前没看过JKDK源码,这次课老师给讲了集合,顺便用HashMap的源码将我击溃。今天花时间看一下HashMap,奋起反击。

一、HashMap基本概念

基本属性

threshold: resize的阈值, 正常等于capacity * loadFactor; 当item数量大于threshold时,

loadFactor: 加载因子,默认0.75

Node组成

image.png

二、伪代码

new HashMap时, 初始化loadFactor;

put(k, v)时,如果是首次put,table为空,先resize(),构建一个新的数组;

put时,做hash处理,找到hash槽,放进去;如果这个槽筒大于树化阈值,就进行树化处理;

put后,如果size > threshold, 就resize, 重新hash。

二、HashMap核心代码分析

1. 实例初始化

HashMap初始化,会使用初始容量和加载因子来初始化。

new HashMap() 初始化结果:threshold=0, loadFactor=0.75, 使用DEFAULT_INITIAL_CAPACITY=16做初始容量

new HashMap(initCapacity) 初始化结果: threshold=大于等于initCapacity的最小2的幂。

new HashMap(initCapacity, loadFactor)

初始化完成后,并不创建容器空间,而是在首次put时创建。

2、容器初始化

首次put时,由于table为null,先走了一次resize()

image.png

首次resize时,oldCap = 0, oldThr = 初始threshold; newCap = 初始threshold, newThr = 初始threshold * 加载因子。根据newCap,初始化数组table。

image.png

3、put时找hash槽

关键算法(容量必须是2的幂,使用位运算,能够秒速找到):

(n - 1) & hash

image.png

4、HashMap扩容

扩容为原容量的2倍,原容量的那些位置被称为low位,新扩出来的被称为high位。重新hash时,要么还在原位置待着,要么被hash到对应的高位去。

image.png

难点解析:如果有当前桶有多个item,则分成两组,一组重hash到low位,一组重hash到高位。

5、树化

树化条件, 根据条件不太容易出现树化的场景。

binCount >= TREEIFY_THRESHOLD - 1 不满足,就不去尝试树化

tab.length >= MIN_TREEIFY_CAPACITY(64) 树化时,不满足只会resize

树化只是树化一个桶的存储。整个table的存储结构并不动。