文章首发于:clawhub.club


HashMap存储结构.jpg

HashMap继承图谱.png

HashMap中的常量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
* 默认初始容量—必须是2的幂。
* 为啥不直接写16??
*/
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16: 又叫做,亦称

/**
* 最大容量,如果较高的值由带参数的任何构造函数隐式指定,则使用该值。必须是2的幂 <= 1<<30。
*/
static final int MAXIMUM_CAPACITY = 1 << 30;

/**
* 构造函数中没有指定时使用的负载因子。
*/
static final float DEFAULT_LOAD_FACTOR = 0.75f;

/**
* 使用树(而不是列表)来设置桶的计数阈值。当向至少具有这么多节点的桶添加元素时,桶将转换为树。
* 该值必须大于2,并且应该至少为8,以便与树木移除中关于收缩后转换回普通桶的假设相吻合。
* 为啥不是 1 << 3 ?
*/
static final int TREEIFY_THRESHOLD = 8;

/**
* 用于在调整大小操作期间反树化(拆分)桶的计数阈值。
* 应小于TREEIFY_THRESHOLD,且最多6个以配合收缩检测下删除。
*/
static final int UNTREEIFY_THRESHOLD = 6;

/**
* 最小的表容量,其中的桶可以树化。(否则,如果一个桶中有太多节点,则会调整表的大小。)
* 应至少为4 * TREEIFY_THRESHOLD,以避免调整大小和treeification阈值之间的冲突。
*/
static final int MIN_TREEIFY_CAPACITY = 64;

HashMap的成员变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
  /**
* 表,第一次使用时初始化,并根据需要调整大小。当分配时,长度总是2的幂。
* (在某些操作中,我们还允许长度为零,以允许当前不需要的引导机制。)
*/
transient Node<K, V>[] table;

/**
* 保存缓存entrySet ()。AbstractMap字段用于keySet()和values()。
*/
transient Set<Entry<K, V>> entrySet;

/**
* 此映射中包含的键值映射的数目。
*/
transient int size;

/**
* 这个HashMap在结构上被修改的次数,结构修改是指改变HashMap中映射的数量或修改其内部结构的次数(例如,rehash)。
* 此字段用于使HashMap集合视图上的迭代器快速失效。(见ConcurrentModificationException)。
*/
transient int modCount;

/**
* 要调整大小的下一个大小值=(capacity * load factor)
*/
int threshold;

/**
* 哈希表的加载因子
*/
final float loadFactor;

参考资料:
https://snailclimb.gitee.io/javaguide/#/./java/HashMap
http://wiki.jikexueyuan.com/project/java-enhancement/java-twentythree.html
https://zhuanlan.zhihu.com/p/21673805
https://blog.csdn.net/v_july_v/article/details/6105630
https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/03.01.md
https://juejin.im/post/5c1244bce51d45532874e275