JDK 1.8 HashMap源码解析

put方法分析

public V put(K key,V value){
	
	return putVal(hash(key),key,value,false,true);
}

hash方法解析

//减少hash冲突
static final int hash(Object key){
	int k ;
	//将hashcode和高16位做一次异或运算,减少hash冲突
	return key==null? 0:(k=key.hashCode())^(k>>>16);
}

putVal方法具体实现(

  • 计算散列位置时,hash%2^n = hash&(2^n-1),
  • 理论上是将hash值对散列表长度 n(默认长度 16)取模,实际则转换成了与运算。
  • 抽象成计算式:X % 2^n = X & (2^n - 1)

final V putVal(int hash,K key,V value,boolean onlyIfAbsent,boolean evict){
	Node<K,V>[] tab,Node<K,V> p,int n,int i;
	if ((tab=tables)==null||(n=tab.length)==0) {
		resize();
	}
    //计算待插入元素的数组下标
	if ((p=(tab[i=(n-1)&hash]))==null) {
		tab[i] = newNode(hash,key,value,null);
		//发生hash冲突
	}
	else{
		K k;Node<K,V> e;
		//key和数组首节点元素相同
		if (hash==p.hash&&((k=p.key )== key ||k!=null&& k.equals(key))) {
			e = p;
			//如果hash值不为首节点,判断是否是红黑树的结点,如果是添加到红黑树中,如果key已存在返回
		}else if (p instanceof TreeNode) {
			e = ((TreeNode<K,V>)p).putTreeNodeval(this,tab,hash,key,value);
			//在链表中
		}
		else{
			for (int bitCount =0; ;bitCount++ ) {
				//遍历找到链表的尾结点
				if ((e=p.next())==null) {
					p.next = newNode(hash,key,value,null);
					//判断链表上结点个数是否为8,如果大于等于8将结点转为红黑树
					if (bitCount>=TRFFIFY_THRESHOLD-1) {
						treeifyBin(tab,hash);
					}
					break;
				}
				//和链表上结点的key相同
				if (e.hash==hash&& ((k=e.key)==key || (k!=null && k.equals(e.key)))) {
					break;
				}
				p = e;
			}
		}
		//key相同,待插入的key有重复
		if (e!=null) {
			V oldValue = e.value;
			if (!onlyIfAbsent||oldValue==null) {
				e.value = value;
			}
			 afterNodeAccess(e);
			return oldValue;

		}

	}
	//待插入的key没有重复,插入成功e结点的值为null
	modCount++;
	//如果元素个数>临界值(数组长度*加载因子),则扩容
	if (++size>threshold) {
		resize();
	}
	afterNodeInsertion(evict);
	return null;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值