JDK1.8的HashMap的源码跟踪及底层实现

JDK1.8的HashMap的底层实现:数组+链表/红黑树

  • 几个常量和变量:
  • (1)DEFAULT_INITIAL_CAPACITY:默认的初始容量 16
  • (2)MAXIMUM_CAPACITY:最大容量 1 << 30
  • (3)DEFAULT_LOAD_FACTOR:默认加载因子 0.75
  • (4)TREEIFY_THRESHOLD:默认树化阈值8,当链表的长度达到这个值后,要考虑树化
  • (5)UNTREEIFY_THRESHOLD:默认反树化阈值6,当树中的结点的个数达到这个阈值后,要考虑变为链表
  • (6)MIN_TREEIFY_CAPACITY:最小树化容量64
  •  	当单个的链表的结点个数达到8,并且table的长度达到64,才会树化。
    
  •  	当单个的链表的结点个数达到8,但是table的长度未达到64,会先扩容
    
  • (7)Node<K,V>[] table:数组
  • (8)size:记录有效映射关系的对数,也是Entry对象的个数
  • (9)int threshold:阈值,当size达到阈值时,考虑扩容
  • (10)double loadFactor:加载因子,影响扩容的频率
  • 1、new HashMap()
  • public HashMap() {
  • //加载因子赋值为0.75
    this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted 其他字段都是默认值
    //threshold是0
    //table=null
    //size = 0
    }
  • 2、put(key,value)
  • (1)如果第一次添加时
  • 把table初始化为长度为16的数组,threshold = 12
  • (2)如果不是第一次添加
  • ①会考虑是否key有重复,那么就替换value
  • ②如果table[i]下面不是树,统计table[i]的结点的个数,添加之前达到7个,考虑树化
  •  当单个的链表的结点个数添加之前达到7,并且table的长度达到64,才会树化。
    
  •  当单个的链表的结点个数添加之前达到7,table的长度未达到64,先扩容。
    
  • ③table[i]下面已经是树,单独处理,直接把新的映射关系连接到树的叶子结点
  • ④添加后,size达到threshold,还要扩容
  • 一旦扩容,就会调整所有映射关系的位置

树化的例子是直接选用自定义类型对象作为key,重写了hashcode方法,使结点都放在一个key下,从而更容易树化

public class TestHashMap8 {
	@Test
	public void test02(){
		HashMap map = new HashMap();
		
		for (int i = 0; i < 15; i++) {
			//这里的key,选用自定义的类型MyKey类型对象
			//选择自定义的类型,是为了控制hashCode值
			map.put(new MyKey(i), "xx");
		}
	}
	
	@Test
	public void test01(){
		HashMap map = new HashMap();
		//添加了15对映射关系
		for (int i = 0; i < 15; i++) {
			//这里选择Integer作为key
			//Integer对象的hashCode
			map.put(i, "xx");
		}
	}
}
class MyKey{
	private int id;

	public MyKey(int id) {
		super();
		this.id = id;
	}

	@Override
	public int hashCode() {
/*		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		return result;*/
		return 1;//所有MyKey的对象的hashCode的值都相同,会存入同一个table[1]中
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		MyKey other = (MyKey) obj;
		if (id != other.id)
			return false;
		return true;
	}
	
}

debug运行代码,树化:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值