通俗易懂的JDK1.8中HashMap源码分析(欢迎探讨指正)+ 典型面试题

面试题在最下面

说到HashMap之前,阅读ArrayList与LinkedList的源码后做个总结

ArrayList 底层是数组,查询效率高,增删效率低

LinkedList底层是双链表,查询效率低,增删效率高 

 这里只是总结看完源码后对hashmap的理解:

hashmap的数据结构?

哈希表:也就是数组+链表,但是当链表达到一定长度时,转为红黑树(JDK1.8之前不转为红黑树)

1.首先,要明确我们插入的的键值对类型的数据是以怎样的形式存储在这样一个hash表结构中的?

是以一个节点的形式存在的,这个节点类Node(HashMap中的静态内部类)包含四个属性,如上小格子里

2.然后任何谈到集合就会涉及到容量,创建HashMap时默认的初始容量为16,负载因子为0.75,临界值16*0.75也就是 12,当然你也可以自己通过有参构造去设置初始容量与负载因子,手动设置的初始容量大于最大容量时,就设置为最大容量,并且设置的初始容量cap会通过tableSizeFor(cap)方法转化为2的次幂数,至于为什么,我只能提示是为了节点的均匀存放,往后面看你应该能猜到。

3.什么是临界值呢,就是数组的元素个数达到这个值时,数组就进行扩容,容量也会乘以2,负载因子也会乘以2

4.然后,我们就用下面两行代码分析HashMap中的这样一个put方法的源码

HashMap<String, Object> map = new HashMap<String, Object>();
map.put("1", "tom");

1.点进put方法,发现是调用的HashMap中的如下方法

2.一步步来,我们看看hash方法里面做了什么,又返回了一个怎样的值?

分析:当key为null的时候返回一个0,不为null时返回key的hashcode h与h无符号右移16位后的值,这里我的理解是,hash()方法为了得到一个不相等的值,而不同对象的hashcode仍可能相同,所以才有了这里的异或处理

3.因为初始数组容量为16,而数组每个节点下又可以挂链表,那么我们新添加进来的节点到底要存放在哪里呢,肯定有个规则,进入putVal方法,据我推测,下面的hash参数就是用来确定位置的

(1)首先先定义了一个节点数组tab,节点p,整数n,i;

(2)继续看,将当前节点数组长度(也就是hashmap的当前容量)存储在n中,这里没经过扩容所以n为16

(3)tab[i = (n - 1) & hash]中: (n-1)&hash与hash%n的效果一样,但是效率更高,这里证明我的猜测是对的了,

就是hash对容量减一取模就是当前节点存在数组的位置了,如果该位置为空闲,就新增节点存进去,万一相等怎么办呢,别急往下看

(4)如果hash值相等,并且key值也相等,那么把节点p赋值给节点e

(5)然后走下面这块代码,onlyIfAbsent从上面可以看到传进来的是false,所以走第二个if,也就是当键相同时把新值替换了旧值,并返回了旧值,那么你可能会问,哪里替换了,这里只是赋值给了e节点的值,提醒下,从上面到这里:

e = p = table[i];//而table[i]就是那个与新增节点键重复的那个节点

 

(6)继续看,当键值不相等p为树形节点时,此时就需要在这棵红黑树上新增该节点,putTreeVal方法我就详细讲解了,下面会讲它里面做了啥

 (7)关于红黑树,我给你们找来了一颗,如下,左节点 < 父节点  < 右节点,并且它是平衡二叉树 红黑树细讲链接,然后,至于怎样存放,还是与hash这个参数有关,按hash的大小组成一颗红黑树,

(8)最后一种情况就是p为链表上的节点,不断遍历直到链表的末尾,插入新增节点后判断新增该节点后链表长度是否大于等于7,为什么是7?不觉得7个节点刚好一颗对称的树么?哈哈,反正我是这样想的,使得空间分布比较均匀

(9)遍历过程中发现key值相同则直接覆盖就完事了

(10)关于扩容,扩容不仅仅是容量增大,节点也会根据(n - 1) & hash重新分配位置,位置只可能在原下标位置或原下标+原容量 的位置

 

先来几个面试题验证所学,先别看答案...

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我才是真的封不觉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值