HashMap执行机制
- 执行构造器 new HashMap()
初始化加载因子 loadfactor = 0.75
HashMap$Node[] table = null;
2. 执行put 会调用 hash方法计算key的hash值
(key==null)?0:(h=key.hashCode())^(h>>>16)
publicVput(Kkey,Vvalue){
returnputVal(hash(key),key,value,false,true);
}
3.执行putVal方法:
finalVputVal(inthash,Kkey,Vvalue,booleanonlyIfAbsent,
booleanevict){
Node<K,V>[]tab;Node<K,V>p;intn,i;
// 如果底层的table 数组为null,或者 length = 0,就扩容到16
if((tab=table)==null||(n=tab.length)==0)
n=(tab=resize()).length;
// 取出hash值对应的table的索引位置的Node(节点),如果为null,就直接把放入的 k - v,创建成一个Node,加入该位置即可.
if((p=tab[i=(n-1)&hash])==null)
tab[i]=newNode(hash,key,value,null);
else{
Node<K,V>e;Kk;
// 如果table的索引位置的key的hash相同和新的key的hash值相同,并 满足(存在的节点的key 和准备添加的key是同一个对象 || equals返回真),就认为不能加入新的k - value.
if(p.hash==hash&&
((k=p.key)==key||(key!=null&&key.equals(k))))
e=p;
elseif(pinstanceofTreeNode)
//如果当前的table的已有的table是已有的Node 是红黑树,就按照红黑树排序.
e=((TreeNode<K,V>)p).putTreeVal(this,tab,hash,key,value);
else{
//如果找到的节点,后面是链表,就循环比较
for(intbinCount=0;;++binCount){ //死循环
if((e=p.next)==null){ //如果整个链表,没有和他相同的,就加到该链表的最后.
p.next=newNode(hash,key,value,null);
//加入后,判断当前链表的个数,是否已经到8个,到8个,就调用 treeifyBin 方法进行红黑树的转换.
if(binCount>=TREEIFY_THRESHOLD-1)//-1for1st
treeifyBin(tab,hash);
break;
}
if(e.hash==hash&& //如果在循环比较中,发现有相同,就break,就只是替换而已.
((k=e.key)==key||(key!=null&&key.equals(k))))
break;
p=e;
}
}
if(e!=null){//existingmappingforkey
VoldValue=e.value;
if(!onlyIfAbsent||oldValue==null)
e.value=value; //替换,key 对应 value
afterNodeAccess(e);
returnoldValue;
}
}
++modCount; //每增加一个Node,就size++
if(++size>threshold)
resize();
afterNodeInsertion(evict);
returnnull;
}
4.关于树化(转成红黑树)
//如果table 为 null ,或者大小还没到 64 ,暂时不树化,而且进行扩容.否则才会真正的树化 -> 剪枝
finalvoidtreeifyBin(Node<K,V>[]tab,inthash){
intn,index;Node<K,V>e;
if(tab==null||(n=tab.length)<MIN_TREEIFY_CAPACITY)
resize();
elseif((e=tab[index=(n-1)&hash])!=null){
TreeNode<K,V>hd=null,tl=null;
do{
TreeNode<K,V>p=replacementTreeNode(e,null);
if(tl==null)
hd=p;
else{
p.prev=tl;
tl.next=p;
}
tl=p;
}while((e=e.next)!=null);
if((tab[index]=hd)!=null)
hd.treeify(tab);
}
}