源码:数组
final Node<K,V>[] resize() {
//旧的数组
Node<K,V>[] oldTab = table;
//旧的容量
int oldCap = (oldTab == null) ? 0 : oldTab.length;
//旧的阈值
int oldThr = threshold;
//新的容量 新的阈值
int newCap, newThr = 0;
if (oldCap > 0) {//若是旧的容量是大于0
if (oldCap >= MAXIMUM_CAPACITY) {//若是旧的容量超过最大容量,阈值设置为integer最大值,返回旧的数组
threshold = Integer.MAX_VALUE;
return oldTab;
}
else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
oldCap >= DEFAULT_INITIAL_CAPACITY)//容量扩充1倍
newThr = oldThr << 1; // double threshold //若是新的容量小于最大容量而且旧的容量大于等于初始化的容量16时,新的阈值扩充1倍
}
else if (oldThr > 0) // initial capacity was placed in threshold
newCap = oldThr;
else { // zero initial threshold signifies using defaults
newCap = DEFAULT_INITIAL_CAPACITY;
newThr = (int)(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);
}
if (newThr == 0) {
float ft = (float)newCap * loadFactor;
newThr = (newCap < MAXIMUM_CAPACITY && ft < (float)MAXIMUM_CAPACITY ?
(int)ft : Integer.MAX_VALUE);
}
threshold = newThr;//阈值设置为新的阈值
@SuppressWarnings({"rawtypes","unchecked"})
Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];//定义新的数组,大小为新的容量
table = newTab;
if (oldTab != null) {
for (int j = 0; j < oldCap; ++j) {//遍历旧的数组
Node<K,V> e;
if ((e = oldTab[j]) != null) {//若是数组中对应的值不为null
oldTab[j] = null;//旧的数组对应值引用为null
if (e.next == null) //e指向的next为null,说明只有一个值,直接根据hash取模移到新的数组中
newTab[e.hash & (newCap - 1)] = e;
else if (e instanceof TreeNode)//若是是红黑树,走红黑树的逻辑
((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
else { // preserve order
//位置不变的链表 低位=0 头和尾
Node<K,V> loHead = null, loTail = null;
//位置变的链表 高位=0 头和尾
Node<K,V> hiHead = null, hiTail = null;
Node<K,V> next;
do {
next = e.next;
if ((e.hash & oldCap) == 0) {//判断对应的hash,属于位置不变仍是须要变
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;
newTab[j + oldCap] = hiHead;//位置须要变的链表 位置为位置迁移(index+oldCap)
}
}
}
}
}
return newTab; //返回新的数组
}
复制代码
链表是红黑树扩容bash
final void split(HashMap<K,V> map, Node<K,V>[] tab, int index, int bit) {
TreeNode<K,V> b = this;
// Relink into lo and hi lists, preserving order
//不须要改变位置的红黑树
TreeNode<K,V> loHead = null, loTail = null;
//须要改变位置的红黑树
TreeNode<K,V> hiHead = null, hiTail = null;
//对应红黑树大小
int lc = 0, hc = 0;
for (TreeNode<K,V> e = b, next; e != null; e = next) {//遍历链表进行分类
next = (TreeNode<K,V>)e.next;
e.next = null;
if ((e.hash & bit) == 0) {
if ((e.prev = loTail) == null)
loHead = e;
else
loTail.next = e;
loTail = e;
++lc;
}
else {
if ((e.prev = hiTail) == null)
hiHead = e;
else
hiTail.next = e;
hiTail = e;
++hc;
}
}
if (loHead != null) {//不须要改变位置的红黑树不为null时
if (lc <= UNTREEIFY_THRESHOLD)//若是大小 小于等于6时,转换成普通的链表
tab[index] = loHead.untreeify(map);
else {
tab[index] = loHead;
if (hiHead != null) // (else is already treeified)
//若是没有须要改变位置的,说明原先的红黑树数据结构没有改变,不然说明数据结构改变了,须要从新转换成对应的红黑树
loHead.treeify(tab);
}
}
if (hiHead != null) {
if (hc <= UNTREEIFY_THRESHOLD)
tab[index + bit] = hiHead.untreeify(map);
else {
tab[index + bit] = hiHead;
if (loHead != null)
//若是原先位置的没有数据,说明原先的红黑树数据结构没有改变,所有都须要移到新的位置,不然说明数据结构改变了,须要从新转换成对应的红黑树
hiHead.treeify(tab);
}
}
}
复制代码
总结:数据结构