/**
* The default initial capacity - MUST be a power of two.
*/
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
// 初始容量大小为16,如果没指定的话
/**
* The load factor used when none specified in constructor.
*/
static final float DEFAULT_LOAD_FACTOR = 0.75f;
// 装载因子默认是 0.75
// 从 Node 的定义来看,HashMap 采用的是链表法存储元素
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
// 指向下一个和当前元素有相同位置索引的元素
Node<K,V> next;
// ... 省略了部分代码
}
final Node<K,V>[] resize() {
// .... 省略了部分代码
threshold = newThr;
// 新的容量的计算策略是如果初始为0,就用默认的16大小,如果大于16小于2^30,每次扩容就double size
// 这里使用新的容量申请了一个新的数组
@SuppressWarnings({"rawtypes","unchecked"})
Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
table = newTab;
// 老数组如果有元素的话,需要做copy且重新计算索引位置
if (oldTab != null) {
// 遍历老数组
for (int j = 0; j < oldCap; ++j) {
Node<K,V> e;
// 不等于null表示元素是一个存在的合法元素,需要copy
if ((e = oldTab[j]) != null) {
oldTab[j] = null;
// 如果当前元素没有后继元素,计算新的位置
if (e.next == null)
newTab[e.hash & (newCap - 1)] = e;
else if (e instanceof TreeNode)
// 如果是树节点类型,这里是红黑树,将树中的节点做分裂,因为容量变化,所以节点计算出的位置索引也会发生变化
((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
else { // preserve order
Node<K,V> loHead = null, loTail = null;
Node<K,V> hiHead = null, hiTail = null;
Node<K,V> next;
// 查找链表中的每一个元素,来计算他们新的位置
do {
next = e.next;
if ((e.hash & oldCap) == 0) {
if (loTail == null)
loHead = e;
else
loTail.next = e;
loTail = e;
}
else {
if (hiTail == null)
hiHead = e;
else
hiTail.next = e;
hiTail = e;
}
} while ((e = next) != null);
if (loTail != null) {
loTail.next = null;
// 使用原来的位置
newTab[j] = loHead;
}
if (hiTail != null) {
hiTail.next = null;
// 使用+oldCap的位置
newTab[j + oldCap] = hiHead;
}
// 这里的位置计算有个数学上的技巧,扩容后新元素的位置要么在原来的位置,要么在原来的值+oldCap的位置
}
}
}
}
}
// 启动扩容的地方,当元素个数大于阈值的时候会触发
// 其中 threshold = Capacity * 装载因子,一切就联系起来了
if (++size > threshold)
resize();
/**
* The table, initialized on first use, and resized as
* necessary. When allocated, length is always a power of two.
* (We also tolerate length zero in some operations to allow
* bootstrapping mechanics that are currently not needed.)
*/
// 使用数组来存放 Node
transient Node<K,V>[] table;
// 从 Node 的定义来看,HashMap 采用的是链表法存储元素
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key; // 存放Key
V value; // 存放 Value
// 指向下一个和当前元素有相同位置索引的元素
Node<K,V> next;
// ... 省略了部分代码
}
/**
* The bin count threshold for using a tree rather than list for a
* bin. Bins are converted to trees when adding an element to a
* bin with at least this many nodes. The value must be greater
* than 2 and should be at least 8 to mesh with assumptions in
* tree removal about conversion back to plain bins upon
* shrinkage.
*/
static final int TREEIFY_THRESHOLD = 8;
/**
* The bin count threshold for untreeifying a (split) bin during a
* resize operation. Should be less than TREEIFY_THRESHOLD, and at
* most 6 to mesh with shrinkage detection under removal.
*/
static final int UNTREEIFY_THRESHOLD = 6;