当前位置: 首页 > news >正文

HashMap学习和线程安全的HashMap

HashMap的底层数据结构?
HashMap在JDK1.8里面的Node数组加链表加红黑树,当链表长度大于8且数组长度大于64,链表转化为红黑树。当红黑树节点数小于6,红黑树转化为链表。在JDK1.7中是数组加链表。

为什么要用红黑树?
当hash冲突严重导致链表长度过长,影响查找性能。红黑树的查找性能相比于链表更好log(n)。

为什么链表转红黑树的阈值是8?
时间和空间的平衡。
时间:当阈值设置的太大,影响查找性能,当阈值设置的太小,红黑树和链表的性能差距不明显
空间:红黑树节点的大小是链表节点的两倍,阈值太小,性能提升不明显,且占据的空间会增大
节点分布在 hash 桶中的频率遵循泊松分布,按照泊松分布的公式计算,当节点数为8,概率非常低,不会导致频繁的转换。

为什么转回链表节点是用的6而不是复用8?
防止节点数在8附近,导致频繁的转换,影响性能。

HashMap的初始容量计算方式?
默认初始容量是16,当传入的值不是2的N次方,会计算成一个大于等于该数组的最小的一个2的N次方。算法为五次左移和或运算,通过最高位的1,拿到2个1、4个1、8个1、16个1、32个1,最后得到的值+1,会得到1个比n 大的 2 的N次方.

为什么HashMap 的容量必须是 2 的 N 次方?
计算索引位置的公式为:(n - 1) & hash,当n的值是2的N次方,n - 1 为低位全是 1 ,此时任何值跟 n - 1 进行 & 运算的结果为该值的低 N 位,达到了和取模同样的效果,实现了均匀分布。&运算比取模运算效率更好。

为什么负载因子默认值是0.75?
时间和空间的考虑。当设置为1,减少了空间,但hash冲突增大,影响查找性能,当设置的较小,空间会浪费较多。

hash的计算方式?
hash函数是先拿到 key 的hashcode,hashCode 的高16位和 hashCode 进行异或(XOR)运算,得到最终的 hash 值。相当于扰动函数,减少hash碰撞,结果更分散。当table 的长度较小的时候,n - 1的低位是1,& hash之后只会获得最低位的值,无论高位怎么变化,都不会影响结果,造成hash碰撞。

为什么红黑树和链表都是通过 e.hash & oldCap == 0 来定位在新表的索引位置?
索引的计算方式(n - 1) & hash,当扩容后,容量是之前的两倍,新的n-1比老的n-1的最高位多了一个1,因此计算新的索引位置时,只取决于高位多出来的这一位,而这一位的值刚好等于oldCap( 两者相减,值是oldCap,2的N次方)。当e.hash & oldCap == 0时,说明oldCap位是0,索引位置为“原索引位置”,当e.hash & oldCap != 0,oldCap位是1,新表索引位置为“原索引 + oldCap 位置”。

HashMap线程不安全体现在什么地方?
1.7 会产生死循环、数据丢失、数据覆盖的问题,1.8 中会有数据覆盖的问题。
当A线程判断index位置为空后正好挂起,B线程开始往index位置的写入节点数据,这时A线程恢复现场,执行赋值操作,就把A线程的数据给覆盖了;还有++size这个地方也会造成多线程同时扩容等问题。

HashMap插入流程?
在这里插入图片描述

HashMap扩容流程?
在这里插入图片描述

相关文章:

  • 蓝桥杯每日一题----货物摆放
  • web架构师编辑器内容-编辑器组件图层面板功能开发-锁定隐藏、键盘事件功能的开发
  • 中级Python面试问题
  • 概率论与数理统计————3.随机变量及其分布
  • STM32F103标准外设库——中断应用/事件控制器(六)
  • 线性代数的学习和整理23:用EXCEL计算 向量/向量组的点乘 (内积) (建设ing)
  • 数据集成时表模型同步方法解析
  • postman后端测试时invalid token报错+token失效报错解决方案
  • 走迷宫(c语言)
  • Firefox 100 正式发布
  • 接口自动化测试持续集成,Soapui接口功能测试参数化
  • npm install 卡住不动的六种解决方法
  • Docker部署Traefik结合内网穿透远程访问Dashboard界面
  • STM32之OLED显示
  • YoloV8改进策略:Agent Attention|Softmax与线性注意力的融合研究|有效涨点|代码注释与改进|全网首发(唯一)
  • Eureka 2.0 开源流产,真的对你影响很大吗?
  • Fastjson的基本使用方法大全
  • Git学习与使用心得(1)—— 初始化
  • HTML5新特性总结
  • Java|序列化异常StreamCorruptedException的解决方法
  • java小心机(3)| 浅析finalize()
  • Netty源码解析1-Buffer
  • PHP那些事儿
  • Spark RDD学习: aggregate函数
  • Spring Security中异常上抛机制及对于转型处理的一些感悟
  • Spring核心 Bean的高级装配
  • Work@Alibaba 阿里巴巴的企业应用构建之路
  • 关于 Cirru Editor 存储格式
  • 解析带emoji和链接的聊天系统消息
  • 如何选择开源的机器学习框架?
  • kubernetes资源对象--ingress
  • ​总结MySQL 的一些知识点:MySQL 选择数据库​
  • ![CDATA[ ]] 是什么东东
  • # centos7下FFmpeg环境部署记录
  • (20)目标检测算法之YOLOv5计算预选框、详解anchor计算
  • (react踩过的坑)antd 如何同时获取一个select 的value和 label值
  • (第二周)效能测试
  • *_zh_CN.properties 国际化资源文件 struts 防乱码等
  • .halo勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET Core IdentityServer4实战-开篇介绍与规划
  • .net core MVC 通过 Filters 过滤器拦截请求及响应内容
  • .Net MVC4 上传大文件,并保存表单
  • .NET 中使用 Mutex 进行跨越进程边界的同步
  • .NET/C# 使窗口永不获得焦点
  • .net2005怎么读string形的xml,不是xml文件。
  • .NET命名规范和开发约定
  • ?php echo ?,?php echo Hello world!;?
  • @Async注解的坑,小心
  • @Bean, @Component, @Configuration简析
  • [acwing周赛复盘] 第 94 场周赛20230311
  • [AI]ChatGPT4 与 ChatGPT3.5 区别有多大
  • [Angular 基础] - 指令(directives)
  • [bzoj 3534][Sdoi2014] 重建
  • [BZOJ1178][Apio2009]CONVENTION会议中心
  • [bzoj1901]: Zju2112 Dynamic Rankings