HashMap知识点
1.基本数据结构

1. JDK1.7 数组 + 链表
2. JDK1.8 数组 + (链表 | 红黑树)
2.树化与退化
1.树化意义
1.红黑树用来避免Dos攻击,防止链表过长时性能下降,树化应该是偶然情况,是保底策略.
2.hash 表的查找,更新的时间复杂度是 O(1),而红黑树的查找,更新的时间复杂度是 O(log2n ),TreeNode 占用空间也比普通 Node 的大,如非必要,尽量还是使用链表
3.hash 值如果足够随机,则在 hash 表内按泊松分布,在负载因子 0.75 的情况下,长度超过 8 的链表出现概率是 0.00000006,树化阈值选择 8 就是为了让树化几率足够小
2.树化规则
1.当链表长度超过树化阈值8时,先尝试扩容来减少链表长度,如果数组容量已经 >= 64,才会进行树化.
3.退化规则
1. 情况1:在扩容时如果拆分树时,树元素 <= 6 则会退化链表
2. 情况2:在 remove 树节点时若 root 根节点,根节点的左右子节点或者孙节点只要有一个为 null 也会退化为链表.
3.索引计算
1.索引计算方法
1.首先,计算对象的hashCode()
2.再进行调用HashMap的hash()方法进行二次哈希 (二次哈希是为了综合高位数据,让哈希分布更为均匀)
3.最后 哈希结果 & (数组容量 - 1) 得到索引位置
2.数组容量为何是2的 n 次幂
1.计算索引时,如果是2的n次幂可以使用位于运算替代取模,效率更高.
2.扩容时 hash & 旧容量 == 0的元素留在原来位置,否则新位置 = 旧位置 + 旧容量
3.上述都是为了配合容量为2的 n 次幂时的优化手段,例如 HashTable的容量就不是2的 n 次幂,并不能说哪种设计更好.
4. put 与 扩容
1. put 流程
1.HashMap 是懒惰创建数组的,首次使用才创建数组
2.计算索引(桶下标)
3.如果桶下标还没人占用,创建 Node 占位返回
4.如果桶下标已经有人占用
1.已经是 TreeNode 走红黑树的添加或更新逻辑
2.是普通 Node,走链表的添加或更新逻辑,如果链表长度超过树化阈值,走树化逻辑
5.返回前检查容量是否超过阈值,一旦超过进行扩容
2. 1.7 与 1.8 的区别
1. 表插入节点时,1.7是头插法,1.8是尾插法
2. 1.7是大于等于阈值且没有空位时才扩容,而1.8是大于阈值就扩容
3. 1.8在扩容计算Node索引时会优化
3. 扩容加载因子 (factor) 为何默认是0.75f
1. 在空间占用和查询时间之间取得比较好的权衡
2. 大于这个值,空间节省了,但是链表就会比较长,影响性能
3. 小于这个值,冲突减少了,但是扩容更频繁,空间占用更多
5.并发问题
1.扩容死链 (1.7会存在)
1.7 源码如下:

void transfer(Entry[] newTable, boolean rehash) {
int newCapacity = newTable.length;
for (Entry<K,V> e : table) {
while(null != e) {
Entry<K,V> next = e.next;
if (rehash) {
e.hash = null == e.key ? 0 : hash(e.key);
}
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
}
}
}

e 和 next 都是局部变量,用来指向当前节点和下一个节点
线程1(绿色)的临时变量 e 和 next 刚引用了这俩节点,还未来得及移动节点,发生了线程切换,由线程2(蓝色)完成扩容和迁移

线程2 扩容完成,由于头插法,链表顺序颠倒。但线程1 的临时变量 e 和 next 还引用了这俩节点,还要再来一遍迁移

第一次循环
循环接着线程切换前运行,注意此时 e 指向的是节点 a,next 指向的是节点 b
e 头插 a 节点,注意图中画了两份 a 节点,但事实上只有一个(为了不让箭头特别乱画了两份)
当循环结束是 e 会指向 next 也就是 b 节点
第二次循环
next 指向了节点 a
e 头插节点 b
当循环结束时,e 指向 next 也就是节点 a

第三次循环
next 指向了 null
e 头插节点 a,a 的 next 指向了 b(之前 a.next 一直是 null),b 的 next 指向 a,死链已成
当循环结束时,e 指向 next 也就是 null,因此第四次循环时会正常退出

HashMap知识点的更多相关文章
- HashMap知识点总结,这一篇算是总结的不错的了,建议看看!
HashMap存储结构 内部包含了⼀个 Entry 类型的数组 Entry[] table.transient Entry[] table;(transient:表示不能被序列化)Entry类型存储着 ...
- HashMap知识点、问题
转载:https://blog.csdn.net/qq_27007251/article/details/71403647 https://www.cnblogs.com/kxdblog/p/4323 ...
- 阿里P7岗位面试,面试官问我:为什么HashMap底层树化标准的元素个数是8
前言 先声明一下,本文有点标题党了,像我这样的菜鸡何德何能去面试阿里的P7岗啊,不过,这确实是阿里p7级岗位的面试题,当然,参加面试的人不是我,而是我部门的一个大佬.他把自己的面试经验分享给了我,也让 ...
- 牛客网Java刷题知识点之为什么HashMap和HashSet区别
不多说,直接上干货! HashMap 和 HashSet的区别是Java面试中最常被问到的问题.如果没有涉及到Collection框架以及多线程的面试,可以说是不完整.而Collection框架的 ...
- 牛客网Java刷题知识点之为什么HashMap不支持线程的同步,不是线程安全的?如何实现HashMap的同步?
不多说,直接上干货! 这篇我是从整体出发去写的. 牛客网Java刷题知识点之Java 集合框架的构成.集合框架中的迭代器Iterator.集合框架中的集合接口Collection(List和Set). ...
- 牛客网Java刷题知识点之Map的两种取值方式keySet和entrySet、HashMap 、Hashtable、TreeMap、LinkedHashMap、ConcurrentHashMap 、WeakHashMap
不多说,直接上干货! 这篇我是从整体出发去写的. 牛客网Java刷题知识点之Java 集合框架的构成.集合框架中的迭代器Iterator.集合框架中的集合接口Collection(List和Set). ...
- 牛客网Java刷题知识点之HashMap的实现原理、HashMap的存储结构、HashMap在JDK1.6、JDK1.7、JDK1.8之间的差异以及带来的性能影响
不多说,直接上干货! 福利 => 每天都推送 欢迎大家,关注微信扫码并加入我的4个微信公众号: 大数据躺过的坑 Java从入门到架构师 人工智能躺过的坑 ...
- HashMap面试知识点
HashMap的工作原理是近年来常见的Java面试题. 几乎每个Java程序员都知道HashMap,都知道哪里要用HashMap,知道Hashtable和HashMap之间的区别,那么为何这道面试题如 ...
- HashMap面试知识点总结
主要参考 JavaGuide 和 敖丙 的文章, 其中也有参考其他的文章, 但忘记保存链接了, 文中图片也是引用别的大佬的, 请见谅. 新手上路, 若有问题, 欢迎指正. 背景 HashMap 的相关 ...
- HashMap几个需要注意的知识点
HashMap简介 HashMap 是java集合框架的一部分. key value都允许null值 (除了非同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同) 不保 ...
随机推荐
- 阿里云免费SSL证书申请全过程(图文详解)
下面我们来详细说下阿里云的域名是如何注册购买,解析绑定的. 首先,打开阿里云官网 万网早就被阿里云收购了,所以是同一家.输入你想购买的域名,我这里是随便输入了"aliyun.com&quo ...
- SSH通过本地开端口打远程隧道
ssh -R 你想让别人连得端口:带外IP:22 root@内网跳板机 -p内网跳板机端口 例如: ssh -R 8888:172.22.200.1:22 root@10.11.11.11 -p202 ...
- Docker for the Virtualization Admin
Docker is one of the most successful open source projects in recent history, and organizations of al ...
- WebUI自动化框架-playwright
(持续更新) 一.环境准备 安装playwright:playwright是基于python3.7开发的第三方包,所以需要使用的python版本是3.7及其以上的 pip install playwr ...
- Gradio 和 Streamlit 安装与使用教程
最近 Sealos Devbox 有点火 ,越来越多的小伙伴都开始使用 Sealos Devbox,有位小伙伴写的文章阅读量已经接近了两万! 评论区有个小伙伴问我能不能出一篇部署 Gradio 和 S ...
- CSP2023总结
CSP2023总结 入门组 比赛开始时,顺序开题. 看完 \(T1\) 后没有立即想出正确解法,有点慌乱,看完 \(T2,T3\) 并思考了一会后过去了大概 \(20\) 分钟,想到了解法便看 \(T ...
- AI运动小程序开发常见问题集锦二
截止到现在写博文时,我们的AI运动识别小程序插件已经迭代了23个版本,成功应用于健身.体育.体测.AR互动等场景:为了让正在集成或者计划进行功能扩展优化的用户,少走弯路.投入更少的开发资源,针对近期的 ...
- php yield使用
在循环一个大数组的时候yield非常好用能节省内存. 比如有个大文件需要读取并处理,如果全部读出来太耗费内存,就可以这样做 <?php function getRows($file) { $ha ...
- 静态分析工具及使用总结(二)CheckStyle
这里主要介绍三种开源的工具,PMD.CheckStyle和FindBugs,着重是在Ant里的调用,据说商业软件JTest也是著名的代码分析工具,哈哈,要花钱的没有用过. Checkstyle (ht ...
- Docker之基础(一)
接触Docker有很久一段时间, 但是没有好好总结一下, 借此公司项目全面容器化, 记录一下常用的Docker操作 概况: 本次容器化的项目包括PHP+Python项目,PHP是基于php-fpm的基 ...