尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

HashMap

HashMap
📅 发布时间:2026/6/19 16:40:12
  • 1.HashMap的数据结构,在jdk8之前使用数组+链表,叫做链地址法,jdk8之后使用的是数组+链表+红黑树,数组容易查询难修改,链表慢查询容易修改,所以两者相结合
  • 2.计算完key哈希值之后,要根据key计算出应该对应的数组下标,这个时候就需要对数组的长度进行取模运算,这里采用的是位运算按位与,因为位运算是直接操作内存数据,不需要从十进制转换成二进制,速度更快一些x%2^n==x&(2 ^n -1),所以HashMap的长度都是2的幂
  • **3.HashMap中几个关键的参数:size()表示插入键值对的个数,capacity表示table(也就是存储链表和红黑树节点的数组)的长度初始默认为16,负载因子loadFactor默认0.75(经过数学推算这个负载因子在0.7左右能在时间和空间上做很好的权衡,因为长度是2的幂,所以乘以0.75正好也是一个整数,并且不会有过多的空余位置浪费),threshold记录了扩容的阈值==capacity*loadfactor **
  • 4.HashMap是如何保证capacity是2的幂呢,第一在初始化的时候如果有设置的大小,会通过位运算转换成一个指定值大的第一个2的幂,第二个就是扩容机制,当size数量超过threshold阈值的时候就会进行扩容
  • 5.在阿里巴巴开发手册上强调过集合类初始化必须指定集合大小,HashMap指定大小最好是 期待空间大小值/负载因子+1这么大,能够有效减少扩容的机制
  • 6.扩容容量是原来的2倍,如果桶节点没有形成链表就直接rehash,如果有链表,就要对节点进行重新链接,如果链表已经形成了树,就取消树化。扩容之后的节点位置要不然就是原位置,要不然就是原索引+原容量,无需重新计算hash值
  • 7.计算hash值的时候采用hash扰动,如果两个key二进制高位不同但是低位相同就很容易产生hash冲突,所以hash扰动就是拔高位置信息混入到低位值,目前jdk8是把计算的hashCode右移16位
  • 8.引入红黑树原因就是如果hash冲突太多,导致某一个桶(bucket)的链表过长,那么查询或者put就无限接近于O(N)复杂度。所以就想使用二叉树,因为left<root<right查询的时间复杂度是logN ,但是如果极端情况一条边特别长又会退化到O(N),所以我们就想到使用二叉平衡树,使得左右两边的高度差维持在1,但是这样的要求又太严格了,要通过不断地左旋或者右旋来维持,又会增加插入元素的时间消耗。最后我们使用了红黑树,他的叶子节点都是黑色的不存储数据,相邻的两个节点不能都是红色的,每一个节点到达叶子结点所包含的黑色节点数是相同的,根节点必须是黑色的。他的插入最多旋转两次,删除最多旋转三次,所以时间复杂度是要优于这个平衡二叉树的
  • 9.为什么不在发生hash冲突的时候就转换成红黑树呢,要等到链表长度为8才进行转换:红黑树的空间是链表的两倍,立即转换之后浪费空间,红黑树虽然查询比链表快,但是插入的时候要进行旋转和变色,所以如果链表长度小于8就转换从时间和空间上来说效果并不好。而且通过数学计算因为hash冲突导致链表长度达到8这个数字概率是很小的,所以官方才指定在8的时候才转换成红黑树。然后在节点数小于6的时候又退化成链表,因为不能一小于8就立马转换回去,这样转换太频繁了
  • 10.首先是在LinkedHashMap中使用了双向链表维护插入顺序,然后HashMap 的普通链表节点Node是没有pre指针的,是树节点TreeNode继承了LinkedHashMap.Entry从而有了pre/next双向链表,避免在Node节点中添加pre产生浪费,java的设计思想“复用优先,按需扩展”,通过双向链表就可以在树退化的时候快速转换成链表,无需重新构建节点之间的关系,包括删除某个中间节点也可以直接用过pre指针找到上一个节点,重新成链
  • 11.如果hashMap元素key没有实现comparable结构拥有比较能力,那么红黑树会使用仲裁方法进行哈希值比较和系统身份哈希值比较
  • 12.在jdk7之前,扩容的时候通常采用的是头插法,当时认为后插入的数据使用的概率更高,成为热点节点,并且不需要遍历一边到尾部,修改next指针变成新的根节点,操作简单只需要O(1)的时间复杂度,但是尾插法就需要遍历到尾部,需要O(n)的时间复杂度,但是如果两个线程同时操作这个链表,就有可能导致节点的next指针互相指向形成环,后续再遍历节点的时候就有可能陷入死循环导致CPU飙升。 所以在jdk8之后改成了尾插法。还存在其他问题比如多个线程put的时候size个数不一样,多个put可能会产生数据覆盖,当既有get又有扩容的时候可能换了桶get不到了
  • 13.hash冲突如何解决:链地址法,开放定址法(在hash数组中寻找空闲的位置来存储,线性探测一个一个往下找空闲的位置,二次探测按照平方来找),再哈希法
  • jdk7和jdk8有那些不一样:数据结构引入红黑树,插入方式变成尾插法,扩容机制从全量rehash变成看新增的那个bit位是1还是0,hash的计算:变成了一次位运算+一次异或

相关新闻

  • windriver 第1章:概述
  • offer选择:优先薪资还是平台?3分钟理清决策思路
  • 价值不在你心里,而在你我之间——用“怎么做”重新定义AI时代的善与恶

最新新闻

  • 6个免费方法让你的手机视频秒变MP4 - 软件工具教程方法
  • Kali Linux实战:ARP欺骗攻击原理、环境搭建与Wireshark流量分析
  • 杭州靠谱品牌首饰回收排行,光谱验金透明称重全款现结 - 奢品小当家
  • 2026年安徽省合肥市合肥医药卫生学校招生简章官网发布:报名入口+报考指南 - cc江江
  • 武汉钻石回收怎么选?2026年实测合规机构名录 - 薛定谔的梨花猫
  • 机器学习模型上线后如何应对系统性风险与数据漂移

日新闻

  • 5分钟掌握Python进化算法:Geatpy高性能优化工具完全指南
  • Microchip 24AA044 EEPROM选型与应用全指南:从参数解析到实战编程
  • 华为的鸿蒙到底有多牛?为什么称作遥遥领先?

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号