put方法(当put第2^30*0.75+1时,则threshold = 2^31,返回旧的2^30的数组。之后不在扩容,直到put到满数组)
a:第一次put值时。(第一个扩容)先创建大小为16的Node类型数组table,threshold为12。后算出p=table[(16-1)& hash],如果p==null,则创建一个Node对象直接放入table[(16-1)& hash]。
b:如果p!=null时。则判断第二次put的key与p.key相同,则p.value=第二次put的value。
c:如果p!=null,p的节点为TreeNode时。则putTreeVal()。
d:如果p!=null,其他情况时(发生hash冲突)。循环p节点的链:1、p.next==null,则向p.next插入创建的Node(当该链有7个+包括数组上的节点=8时,且数组的容量>=64时,在向该链put时,该链变树)。2、p.next!=null,p.key与put的key相同。则则p.value=put的value。
e:(第二次扩容)当table的大小变为13时:第一步:threshold变为oldThreshold<<1=24,table的大小变为newCap = oldCap<<1=32。第二步:循环老的数组oldTab(大小为16),递增变量为j,oldTab[j]为null则不任何操作,否则(1.判断oldTab[j].next==null,则计算index=oldTab[j].hash & 31,放入新的大小为32的数组。2.判断oldTab[j]为TreeNode,则oldTab[j].split。3.根据条件oldTab[j].hash & oldCap ==0意思为oldTab[j].hash的二进制的第5位等于0,将满足条件的Node组成一个低链,放在newTab[j]上,将不满足条件的Node组成一个高链,放在newTab[j+oldCap])。
//双参构造
public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " +
loadFactor);
this.loadFactor = loadFactor;
// threshhold为大于initialCapacity值,2的n次方值
// 例如initialCapacity=10,或11,或12。threshold=2^4=16
// initialCapacity=10000。threshold=2^14=16384
// 在调用put时,会发生扩容:newCap=threshold,newThr=newCap*loadFactor
this.threshold = tableSizeFor(initialCapacity);
}
// HashMap的默认构造方法中,初始化loadFactor=0.75
// 属性 DEFAULT_INITIAL_CAPACITY = 1 << 4 =16;1X2^4;
V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
//临时变量
Node<K,V>[] tab; Node<K,V> p; int n, i;
// 第一次put值时
if ((tab = table) == null || (n = tab.length) == 0)
//第一个扩容时,threshold=0变为16*0.75=12
// Node<K,V>[] resize()->{
// //new一个大小为16的Node类型的数组,返回
// Node<K,V>[] table = (Node<K,V>[])new Node[newCap];
// retrun table;
// }
// n=12
n = (tab = resize()).length;
// 计算tab数组的index。如果tab[index]==null,就new
// hash=key.hashCode() ^ key.hashCode()>>> 16
if ((p = tab[i = (n - 1) & hash]) == null)
//用Node类的全参构造创建一个对象,
tab[i] = newNode(hash, key, value, null);
else{
//tab[index]不为null,说明之前put过,p = tab [index];
//之前key的hash是否与当前put的key的hash是否相等 &&
// ( 之前的key 是否等于 当前的key || (当前key不为null && 当前key等与之前的key))
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
// 该节点是否为TreeNode节点
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else{
// 死循环,记录循环次数
for (int binCount = 0; ; ++binCount) {
// 将p节点的next节点赋值给e,判断e==null
if ((e = p.next) == null) {
// 在tab[index]的节点p.next赋值
p.next = newNode(hash, key, value, null);
//当binCount=7,treeifyBin()
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
//e!=null
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
//在put第13个不同的key时,进行扩容。12->13
//大小为16的table表中里存13个Node时,开始扩容resize();
// Node<K,V>[] resize()->{
// //创建新的变量接收老的数组
// Node<K,V>[] oldTab = table;
// int threshold = newCap = table.length << 1= 16 <<1 =32;
// int newThr = oldThr << 1 = 24;
// //new 大小为32的Node数组
// Node<K,V>[] table = newTab = (Node<K,V>[])new Node[newCap];
// if (oldTab != null) {
// //循环旧的table ,存了13个值,循环16次
// for (int j = 0; j < oldCap; ++j) {
// //创建临时变量
// Node<K,V> e;
// //oldTab[0]不为空,将oldTab数组值赋值给e
// if ((e = oldTab[j]) != null) {
// //将数组oldTab[0]置为null
// oldTab[j] = null;
// //判断e节点的next节点
// if (e.next == null)
// //计算index,将e.hash与新的容量32作&
// //并赋值
// newTab[e.hash & (newCap - 1)] = e;
// //判断该节点为树节点
// else if (e instanceof TreeNode)
// ((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
// //e.next !=null
// else { // preserve order
// //常见多个临时变量
// Node<K,V> loHead = null, loTail = null;
// Node<K,V> hiHead = null, hiTail = null;
// Node<K,V> next;
// //循环,将e = e.next
// do {
// //next为e.next
// next = e.next;
// //判断e.hash & oldCap==0
// // 则 loHead=loTail=e
// // 否则 hiHead=hiTail=e
// if ((e.hash & oldCap) == 0) {
// if (loTail == null)
// loHead = e;
// else
// //给前一个节点的next赋值e
// loTail.next = e;
// //重置loTail,赋值为当前e
// loTail = e;
// }
// else {
// if (hiTail == null)
// hiHead = e;
// else
// hiTail.next = e;
// hiTail = e;
// }
// } while ((e = next) != null);
// // 在newTab[j] 上的Node对象循环结束,
// // e=null,
// // 将loTail.next =null
// if (loTail != null) {
// //低链尾部节点的next置为null
// loTail.next = null;
// newTab[j] = loHead;
// }
// // hiTail
// // j+16=hiHead节点
// if (hiTail != null) {
// //高链尾部节点的next置为null
// hiTail.next = null;
// newTab[j + oldCap] = hiHead;
// }
// }
// }
// }
// }
// return newTab;
// }
if (++size > threshold)
resize();
}
}
//HashMap内部类的Node数据结构
// 该类有key和key对应的hash值,及value,和下一个Node数据。
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}