一篇文章,轻松拿捏大厂必问的HashMap源码分析

目录

一,JDK8之后HashMap的新特性

二,hashMap源码属性解读

(一),默认初始化容量数量:16

(二),最大数组容量:2^30

(三),默认负载因子:0.75f

(四),触发树化条件1,链表阈值:

(五),解树化的阈值:

 (六),触发树化条件二,hash桶阈值(数组元素个数):

三,HashMap的put方法

(一)put方法

(二),hash方法()

  (三),putVal方法

 put方法的核心逻辑: 

四,hashMap的构造方法

(一),无参构造

(二),有参构造

 五,resize()方法

六,关于Map和Set的关系


一,JDK8之后HashMap的新特性

JDK8之后的hashMap,采用   数组+链表+红黑树  的结构 

当链表冲突严重时,会将链表转换成红黑树的结构,提高查询效率。

冲突严重:是指

JDK8之前,hashMap采用 数组 + 链表的结构

二,hashMap源码属性解读

(一),默认初始化容量数量:16

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;

(二),最大数组容量:2^30

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

(三),默认负载因子:0.75f

static final float DEFAULT_LOAD_FACTOR = 0.75f;

(四),触发树化条件1,链表阈值:

链表的长度超过8,并且桶的个数达到64,就会触发链表转为树结构,否则只是数组扩容。

static final int TREEIFY_THRESHOLD = 8;

 

(五),解树化的阈值:

当树的节点个数为6时,就会触发解树化转为链表。

static final int UNTREEIFY_THRESHOLD = 6;

 (六),触发树化条件二,hash桶阈值(数组元素个数):

static final int MIN_TREEIFY_CAPACITY = 64;

 当数组个超过64,并且某个链表的节点个数  >  8 时,同时满足这两个条件,才会触发树化。

三,HashMap的put方法

(一)put方法

(二),hash方法()

例如:

此时计算下来得结果并不是hash索引,长江此时计算得值传入到putVal中进一步运算才能得到真正得下标。

  (三),putVal方法

 采用&运算得原因:

这里hash表得长度为2^i,采用&是为压榨性能,

原因:n = 16 任意正整数 x ,   x & (n - 1) == x % n; 并且得到得结果 res < n,保证了索引在hash表的范围之内。

&&位运算得速率远大于数学运算。

 put方法的核心逻辑: 

 equals相同的两个对象,那么他们的hashCode一定相同,原因:两个对象时相同的,那么经过hash运算,得到的hashCode一定相同,

hashCode相同的两个对象,equals不一定相同,原因:当发生了hash冲突,他们的hash值相同,但对象不同。

四,hashMap的构造方法

(一),无参构造

懒加载模式:在创建时,不开辟空间,只有在第一次添加元素时,才开始对表扩容。

resize()方法既是扩容方法,也是初始化方法。

(二),有参构造

 

 五,resize()方法

resize()方法既是扩容方法,也是初始化方法。

六,关于Map和Set的关系

Set集合实际上就是用Map集合的key保存的,这也就保证了Set的不可重复性。

HashSet使用HashMap的key保存,这就保证了HashSet可以为空,null全部保存在map的0位置。

TreeSet使用TreeMap的key保存的,也就保证了TreeSet不可以为空。

猜你喜欢

转载自blog.csdn.net/qq_52655865/article/details/125004534