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

深入解析HashMap:30道经典面试题带你彻底搞懂

深入解析HashMap30道经典面试题带你彻底搞懂HashMap是Java面试中的“常客”无论是初级还是高级开发工程师HashMap相关的问题几乎都会出现在面试中。本文将汇总最经典的HashMap面试题从基础原理到源码分析帮助你在面试中游刃有余。目录基础概念篇源码深度篇并发安全篇实战经验篇性能优化篇基础概念篇1. 什么是HashMap它的底层数据结构是什么答HashMap是基于哈希表的Map接口实现以key-value形式存储数据。JDK 1.8之前底层采用数组链表的结构JDK 1.8及以后采用数组链表红黑树的结构。当链表长度超过阈值默认为8且数组长度大于64时链表会转换为红黑树以提高查询效率。2. HashMap和Hashtable有什么区别比较维度HashMapHashtable线程安全非线程安全线程安全synchronized允许nullkey和value都允许null不允许null初始容量1611扩容机制2倍扩容2倍1扩容继承关系AbstractMapDictionary已废弃3. 什么是哈希冲突HashMap如何解决哈希冲突答哈希冲突指不同的key经过hash函数计算后得到相同的数组下标位置。HashMap采用链地址法解决哈希冲突当发生冲突时将新节点插入到对应下标的链表中JDK 1.8之前采用头插法JDK 1.8后采用尾插法当链表长度超过阈值转换为红黑树优化查询性能源码深度篇4. HashMap的put方法执行流程是怎样的// 简化版put流程1.计算key的hash值hash(keynull)?0:(hkey.hashCode())^(h16)2.检查table数组是否初始化未初始化则resize()3.计算下标i(n-1)hash4.如果该位置为空直接插入新节点5.如果该位置不为空-如果key相同直接覆盖value-如果是红黑树节点插入红黑树-如果是链表节点遍历链表*找到相同key则覆盖*未找到则在链表尾部插入新节点*检查链表长度是否超过阈值(8)超过则树化6.检查size是否超过threshold超过则resize()5. 为什么HashMap的容量必须是2的幂次方主要原因为了高效计算数组下标和减少哈希冲突。// 计算下标的代码index(n-1)hash// n为数组长度如果n是2的幂次方n-1的二进制形式全是1与hash做与运算时结果取决于hash的低位分布更均匀如果n不是2的幂次方n-1的二进制包含0与运算会屏蔽部分hash位增加冲突概率位运算()比取模运算(%)效率更高6. HashMap的hash函数是如何设计的为什么要这样设计staticfinalinthash(Objectkey){inth;return(keynull)?0:(hkey.hashCode())^(h16);}设计目的让高位也参与下标计算减少哈希冲突。原理获取key的hashCode()32位int值将hashCode的高16位与低16位进行异或运算这样在数组长度较小时高位特征也能保留下来例子假设n16n-115(二进制00001111)如果不做扰动直接使用hashCode只有低4位参与运算扰动后高位特征混入低16位分布更均匀7. 什么是加载因子为什么默认是0.75答加载因子是HashMap在扩容前允许达到的填充程度计算公式threshold capacity * loadFactor。默认值0.75的原因时间和空间的平衡折中。加载因子过高如1空间利用率高但哈希冲突增加查询效率降低加载因子过低如0.5哈希冲突减少但空间浪费大频繁扩容0.75是统计学得出的较优值泊松分布下链表长度达到8的概率极小8. 为什么JDK 1.8要将链表转换为红黑树的阈值设为8答基于时间和空间复杂度的权衡以及泊松分布的计算。根据泊松分布在加载因子为0.75的情况下哈希桶中链表长度的概率长度为00.60653066长度为10.30326533长度为20.07581633长度为30.01291061长度为40.00160452长度为50.00014379长度为60.00001145长度为70.00000094长度为80.00000006当链表长度达到8时概率已经极低千万分之六此时转为红黑树既不会太频繁也能应对极端情况下的性能问题。9. HashMap的扩容机制是怎样的// 扩容关键步骤1.新容量旧容量12倍扩容2.新阈值新容量*加载因子3.创建新数组2倍大小4.重新计算每个元素的位置-如果e.hasholdCap0元素位置不变原索引-否则新位置原索引oldCap为什么可以这样计算因为容量是2的幂次方扩容后n-1比原来多了一个高位1通过hash值的新增高位是0还是1可以快速判断元素的新位置避免了JDK 1.7中重新计算hash的损耗10. JDK 1.8中HashMap做了哪些优化优化点JDK 1.7JDK 1.8数据结构数组链表数组链表红黑树插入方式头插法尾插法hash计算多次扰动1次异或运算扩容重定位重新hash直接判断高位链表插入容易形成死循环解决死循环问题并发安全篇11. HashMap是线程安全的吗为什么答HashMap不是线程安全的。在多线程环境下会出现以下问题JDK 1.7扩容时头插法可能导致循环链表引起CPU 100%JDK 1.8虽然解决了循环链表问题但仍存在数据覆盖问题如put时两个线程同时检测到空桶都会插入数据12. 什么是ConcurrentHashMap它如何保证线程安全答ConcurrentHashMap是线程安全的HashMap实现。JDK 1.7实现分段锁(Segment)默认16个Segment每个Segment继承ReentrantLock理论上支持16个线程并发写入锁粒度较粗JDK 1.8实现CAS synchronized放弃分段锁使用Node数组CASsynchronized锁粒度更细锁单个桶并发度更高13. 如何在多线程环境下使用HashMap方案一使用Collections.synchronizedMap()MapmapCollections.synchronizedMap(newHashMap());方案二使用Collections.synchronizedMap()MapmapnewConcurrentHashMap();方案三使用Collections.synchronizedMap()MapmapnewHashtable();推荐优先使用ConcurrentHashMap并发性能最好。14. 为什么JDK 1.7的HashMap在多线程扩容时会出现死循环原因头插法导致链表反转时形成环。场景线程1和线程2同时扩容线程1执行到一半被挂起线程2完成扩容后链表顺序反转。线程1恢复后引用关系混乱形成循环链表导致get操作陷入死循环。解决JDK 1.8改为尾插法保持链表原有顺序避免循环链表。实战经验篇15. 如果使用自定义对象作为HashMap的key需要注意什么必须重写hashCode()和equals()方法publicclassPerson{privateStringid;privateStringname;Overridepublicbooleanequals(Objecto){if(thiso)returntrue;if(onull||getClass()!o.getClass())returnfalse;Personperson(Person)o;returnObjects.equals(id,person.id);}OverridepublicinthashCode(){returnObjects.hash(id);}}原则两个对象equals相等hashCode必须相等两个对象hashCode相等equals不一定相等16. HashMap中key为null时存储在哪里答存储在table[0]的位置。// HashMap的hash方法staticfinalinthash(Objectkey){inth;// key为null时hash值为0return(keynull)?0:(hkey.hashCode())^(h16);}17. 如何遍历HashMap哪种方式效率最高// 方式1使用entrySet推荐for(Map.EntryString,Stringentry:map.entrySet()){Stringkeyentry.getKey();Stringvalueentry.getValue();}// 方式2使用keySet getfor(Stringkey:map.keySet()){Stringvaluemap.get(key);// 多了一次查询}// 方式3使用iteratorIteratorMap.EntryString,Stringiteratormap.entrySet().iterator();while(iterator.hasNext()){Map.EntryString,Stringentryiterator.next();}// 方式4Java 8 forEachmap.forEach((key,value)-{System.out.println(key:value);});效率对比entrySet ≈ forEach keySetkeySet需要多一次get查询18. HashMap和LinkedHashMap有什么区别特性HashMapLinkedHashMap顺序无序可预测的迭代顺序插入顺序或访问顺序性能略高略低需要维护双向链表实现数组链表红黑树继承HashMap增加双向链表用途通用场景LRU缓存、需要有序的场景LRU缓存示例// 构建LRU缓存LinkedHashMapString,StringlruCachenewLinkedHashMapString,String(16,0.75f,true){OverrideprotectedbooleanremoveEldestEntry(Map.EntryString,Stringeldest){returnsize()10;// 最多缓存10个}};19. HashMap和TreeMap有什么区别特性HashMapTreeMap顺序无序自然顺序或自定义顺序底层结构哈希表红黑树时间复杂度O(1)O(log n)允许nullkey可为nullkey不能为null会抛异常接口MapMap SortedMap性能优化篇20. 如何初始化HashMap才能避免频繁扩容估算初始容量// 需要存储100个元素加载因子0.75// 容量 100 / 0.75 ≈ 134取2的幂次方256MapmapnewHashMap(256);计算公式初始容量 (需要存储的元素数量 / 加载因子) 1计算方法初始容量 (需要存储的元素数量 / 加载因子) 1工具方法:MapString,StringmapnewHashMap((int)(100/0.75f)1);// 或者使用GuavaMapString,StringmapMaps.newHashMapWithExpectedSize(100);21. HashMap的查询时间复杂度是多少最好情况O(1) - 无哈希冲突最坏情况O(log n) - 全部在红黑树中平均情况接近O(1) - 哈希函数分布均匀22. 为什么重写equals时必须重写hashCode反例publicclassStudent{privateStringid;// 只重写equals没重写hashCodepublicbooleanequals(Objectobj){// ...}}MapStudent,StringmapnewHashMap();map.put(newStudent(001),张三);map.get(newStudent(001));// 返回null原因HashMap先比较hashCode如果hashCode不同直接认为key不同不会调用equals。两个对象equals相等但hashCode不同会导致无法从HashMap中获取值。23. String类型的key有什么优势答String作为HashMap的key有以下优势不可变性保证了hashCode不会变化hashCode缓存String内部缓存了hashCode计算一次后重复使用良好的hash分布String的hash算法经过优化冲突较少24. HashMap的key一般使用什么类型推荐使用不可变类StringInteger、Long等包装类自定义不可变类所有字段final避免使用可变对象作为key否则修改对象后会导致无法找到原来的value。25. 如何计算HashMap占用的内存大小粗略估算每个Entry对象约32字节对象头key引用value引用hashnext空数组16 * 引用大小8字节 128字节存储n个元素约 n * 32 数组大小精确计算使用Java对象内存计算工具如jol-core26. 什么是扰动函数为什么需要它答扰动函数是指将高位特征混合到低位的操作如HashMap中的hash ^ (hash 16)。目的当数组长度较小时让高位也参与下标计算使数据分布更均匀减少冲突。类比就像将一桶水的上层和下层的混合后再倒出避免只有底层的水被使用。27. 红黑树在HashMap中起到什么作用作用优化极端情况下的查询性能。正常情况下链表查询时间复杂度O(n)链表长度超过8时查询效率下降转换为红黑树后查询时间复杂度降为O(log n)节点数小于6时会转换回链表避免频繁转换28. HashMap的fail-fast机制是什么答HashMap的迭代器采用fail-fast机制当多个线程同时修改HashMap时会抛出ConcurrentModificationException。MapString,StringmapnewHashMap();Iteratoritmap.entrySet().iterator();map.put(key,value);// 修改操作while(it.hasNext()){// 抛出ConcurrentModificationExceptionit.next();}原理HashMap内部维护modCount变量记录修改次数。每次迭代时比较modCount是否变化。29. 什么是容量、大小和阈值容量(capacity)哈希表数组的长度默认为16大小(size)HashMap中实际存储的键值对数量阈值(threshold)允许存储的最大键值对数量capacity * loadFactor超过阈值需要扩容30. 手写一个简单的HashMap实现publicclassSimpleHashMapK,V{privateNodeK,V[]table;privateintsize;privatestaticfinalintDEFAULT_CAPACITY16;staticclassNodeK,V{finalinthash;finalKkey;Vvalue;NodeK,Vnext;Node(inthash,Kkey,Vvalue,NodeK,Vnext){this.hashhash;this.keykey;this.valuevalue;this.nextnext;}}publicSimpleHashMap(){tablenewNode[DEFAULT_CAPACITY];}privateinthash(Objectkey){inth;return(keynull)?0:(hkey.hashCode())^(h16);}publicvoidput(Kkey,Vvalue){inthashhash(key);intindex(table.length-1)hash;if(table[index]null){table[index]newNode(hash,key,value,null);}else{NodeK,Vnodetable[index];NodeK,Vprevnull;while(node!null){if(node.hashhash(node.keykey||(key!nullkey.equals(node.key)))){node.valuevalue;return;}prevnode;nodenode.next;}prev.nextnewNode(hash,key,value,null);}size;}publicVget(Kkey){inthashhash(key);intindex(table.length-1)hash;NodeK,Vnodetable[index];while(node!null){if(node.hashhash(node.keykey||(key!nullkey.equals(node.key)))){returnnode.value;}nodenode.next;}returnnull;}}总结HashMap是Java程序员必须掌握的核心知识。通过以上30道面试题我们深入了解了HashMap的底层原理数组链表红黑树的数据结构核心机制hash计算、下标定位、扩容重定位设计哲学空间与时间的权衡并发问题线程不安全的根源及解决方案最佳实践初始化容量、key的选择等掌握这些知识点不仅能应对面试更能帮助我们在实际开发中写出更高效、更健壮的代码。最后的小建议面试时不要死记硬背答案要理解背后的设计思想和权衡这样才能在面试官的追问下游刃有余。祝你面试成功

相关文章:

深入解析HashMap:30道经典面试题带你彻底搞懂

深入解析HashMap:30道经典面试题带你彻底搞懂 HashMap是Java面试中的“常客”,无论是初级还是高级开发工程师,HashMap相关的问题几乎都会出现在面试中。本文将汇总最经典的HashMap面试题,从基础原理到源码分析,帮助你…...

Ollama安装-运行模型-常用运维命令

方法1:官方命令行安装 安装: curl -fsSL https://ollama.com/install.sh | sh 注:需要网络支持,可以安装的话就不需要执行手动安装的配置,官方脚本会把所有东西都配置好,如果要修改镜像源可查看后面修改镜像…...

[特殊字符] 第88课:目标和

想系统提升编程能力、查看更完整的学习路线,欢迎访问 AI Compass:https://github.com/tingaicompass/AI-Compass 仓库持续更新刷题题解、Python 基础和 AI 实战内容,适合想高效进阶的你。 📖 第88课:目标和 模块:动态规划 | 难度:…...

[特殊字符] 第87课:股票含冷冻期

想系统提升编程能力、查看更完整的学习路线,欢迎访问 AI Compass:https://github.com/tingaicompass/AI-Compass 仓库持续更新刷题题解、Python 基础和 AI 实战内容,适合想高效进阶的你。📖 第87课:股票含冷冻期模块:动态规划 | 难…...

从付费软件到自主开发:我用AI和FFmpeg实现了一个录屏工具淌

我为什么会发出这个疑问呢?是因为我研究Web开发中的一个问题时,HTTP请求体在 Filter(过滤器)处被读取了之后,在 Controller(控制层)就读不到值了,使用 RequestBody 的时候。 无论是字…...

HJ169 灵异背包?

题目题解(36)讨论(22)排行 简单 通过率:43.17% 时间限制:1秒 空间限制:256M 知识点贪心 校招时部分企业笔试将禁止编程题跳出页面,为提前适应,练习时请使用在线自测,而非本地IDE。 描述 给定 nn 个正…...

Piggy_Packages V2026.1 帮助文档(七)WRFDA同化试验

数值天气预报的主要误差来源于初始场的误差。资料同化(Data Assimilation)是一种将观测资料与数值天气预报(NWP)产品及其各自的误差统计数据相结合的技术,旨在为数值模式提供更加准确的初始场。 在“Piggy_Packages V…...

Serverless 架构设计与实践:构建高效的无服务器应用

Serverless 架构设计与实践:构建高效的无服务器应用 前言 作为一个在数据深渊里捞了十几年 Bug 的女码农,我深知 Serverless 架构在现代云原生应用中的重要性。随着云计算的发展,Serverless 架构以其按需付费、自动扩缩容等特性&#xff0c…...

OpenClaw+千问3.5-9B智能家居:自然语言控制家庭设备

OpenClaw千问3.5-9B智能家居:自然语言控制家庭设备 1. 为什么需要自然语言控制智能家居? 去年装修新房时,我装了整整27个智能设备——从客厅的吸顶灯到厨房的窗帘电机,甚至马桶盖都接入了米家系统。但很快发现一个问题&#xff…...

知识竞赛软件如何选择?抢答器功能

知识竞赛软件怎么选?抢答器功能是关键 组织一场精彩、公平、高效的知识竞赛,离不开专业软件的支持。在众多功能中,抢答器功能往往是决定竞赛成败的核心。本文将系统性地探讨如何选择一款合适的知识竞赛软件,并深入分析抢答器功能…...

Qwen3.5-千问 ZGC在Linux和Windows实现有何区别?

ZGC 在 Linux 和 Windows 上的核心算法(如着色指针、读屏障、并发标记/重定位)是完全一致的,但在底层操作系统接口调用、内存映射实现细节以及平台支持成熟度上存在显著差异。 以下是 ZGC 在 Linux 和 Windows 实现上的主要区别对比&#xff…...

揭秘OZON选品公司性价比:如何用最少的钱选出爆款?

在OZON平台上掘金,选品无疑是决定成败的第一步。然而,面对海量商品和瞬息万变的市场,许多卖家陷入了两难:要么投入大量时间和金钱盲目试错,要么依赖昂贵的选品工具,成本高企却收效甚微。今天,我…...

OpenClaw+SecGPT-14B实战:Git仓库敏感信息自动化审计

OpenClawSecGPT-14B实战:Git仓库敏感信息自动化审计 1. 为什么需要自动化敏感信息审计 去年我在维护一个开源项目时,意外发现某次提交中包含了AWS密钥。虽然及时撤销了提交,但这件事让我意识到:人工检查Git历史就像大海捞针。传…...

audio policy config xml解析过程

一、获取xml文件1.启动audioserviceframeworks/av/media/audioserver/main_audioserver.cpp //main函数中定义一个对象&#xff1a; const auto aps sp<AudioPolicyService>::make();2.执行构造函数并mCreateAudioPolicyManager(createAudioPolicyManager)进行初始化fra…...

《AI Agent生产力部署指南:OpenClaw + vLLM 本地化实战——(三)OpenClaw与LLM工具链适配》

上一章节中我们完整介绍了如何在服务器中配置vLLM服务,如何运行vLLM,以及如何搭建本地机器作为中间跳转连接虚拟机与服务器的通信。 本章第五节完成最后一个步骤对openclaw的相关配置,让本地能成功对话虚拟机,虚拟机成功调用服务器模型。 下面直接开始吧! (五)配置ope…...

PRD文档模板

xxxxxx 需求规格说明书 南京市xxx信息服务有限公司 修订记录 版本号 修订日期 修订人 修订描述 V1.0 20190203 xxxxx 初稿 一、概述 1.1需求背景 说明需求背景&#xff0c;为什么要做该需求&#xff0c;主要是为了解决什么问题等 背景举例&#xff1a;目前…...

需求用例的写法

一、为什么写需求用例 流程图为需求用例提供了关键路径&#xff0c;而需求用例则是对业务场景的全面还原。本文将从以下四个方面阐述用例的信息&#xff1a; 用例的定义用例的粒度用例的例子用例的关键点解释 我写需求文档有几大准则&#xff0c;是需要时刻铭记和实践的&…...

Windows下OpenClaw全攻略:Qwen3-14B镜像接入与自动化测试

Windows下OpenClaw全攻略&#xff1a;Qwen3-14B镜像接入与自动化测试 1. 为什么选择WindowsOpenClaw组合 去年我在尝试自动化办公流程时&#xff0c;发现Mac环境下的OpenClaw虽然安装便捷&#xff0c;但团队里多数同事仍在使用Windows系统。为了让这套工具真正落地&#xff0…...

这个免费AI工具太狠了:我每周省下10小时学习时间

这个免费AI工具太狠了&#xff1a;我每周省下10小时学习时间 改写自 The PyCoach 于 2026 年 3 月 20 日发布的文章《NotebookLM: The Best AI Tool to Learn Any Topic Faster》&#xff0c;并参考 Diana Dovgopol 的共同观点。 很多人以为&#xff0c;学习慢&#xff0c;是因…...

WiFiEspAT:基于AT指令的嵌入式Wi-Fi协处理器适配库

1. 项目概述WiFiEspAT 是一个面向嵌入式系统的轻量级、高可靠性网络适配层库&#xff0c;其核心目标是将 ESP8266 或 ESP32 模块作为独立的 Wi-Fi 网络协处理器&#xff08;Network Coprocessor&#xff09;&#xff0c;通过标准 AT 指令集与主控 MCU&#xff08;如 AVR、ARM C…...

IEEE/ASME Transactions on Mechatronics | 院士团队让移动机器人在复杂环境中学会主动避障

论文信息 英文题目&#xff1a; Vector Field Augmented Reinforcement Learning for Adaptive Motion Planning of Mobile Robots 中文题目&#xff1a;面向移动机器人自适应运动规划的向量场增强强化学习 作者&#xff1a; Yang Lu, Weijia Yao, Cong Li, Yongqian Xia…...

DigitLed72xx库:工业级MAX7219/7221数码管驱动方案

1. DigitLed72xx 库概述&#xff1a;面向工业级 LED 显示控制的嵌入式驱动框架DigitLed72xx 是一款专为 MAX7219 和 MAX7221 七段数码管显示驱动芯片设计的轻量级、高可靠性嵌入式 C 库。该库并非简单的 Arduino 封装&#xff0c;其底层架构深度适配硬件 SPI 外设&#xff0c;支…...

【2026年最新600套毕设项目分享】基于微信小程序的科创微应用平台(30012)

有需要的同学&#xff0c;源代码和配套文档领取&#xff0c;加文章最下方的名片哦 一、项目演示 项目演示视频 二、资料介绍 完整源代码&#xff08;前后端源代码SQL脚本&#xff09;配套文档&#xff08;LWPPT开题报告/任务书&#xff09;远程调试控屏包运行一键启动项目&…...

【2026年最新600套毕设项目分享】微信小程序的医院核酸检测服务系统(30011)

有需要的同学&#xff0c;源代码和配套文档领取&#xff0c;加文章最下方的名片哦 一、项目演示 项目演示视频 二、资料介绍 完整源代码&#xff08;前后端源代码SQL脚本&#xff09;配套文档&#xff08;LWPPT开题报告/任务书&#xff09;远程调试控屏包运行一键启动项目&…...

2025_NIPS_CRRL: Learning Channel-invariant Neural Representations for High-performance Cross-day ...

文章核心总结 本文提出CRRL(Channel Rearrangement and Reconstruction Learning)框架,用于解决脑机接口(BCI)跨天解码中神经信号的通道级变异性问题,实现长期稳定解码。核心创新在于通过两个专用模块分别处理神经元丢失/新增、电极漂移两类变异,在多数据集上达成超两个…...

AI+声学:当物理规律遇见神经网络,如何颠覆传统模拟?

AI声学&#xff1a;当物理规律遇见神经网络&#xff0c;如何颠覆传统模拟&#xff1f; 引言 想象一下&#xff0c;模拟一个大型音乐厅的声场分布&#xff0c;传统方法可能需要超级计算机数小时的计算&#xff0c;而AI模型仅需秒级响应。这并非科幻&#xff0c;而是“AI for Sci…...

AI+电磁:当计算电磁学遇上人工智能,一场效率革命正在发生

AI电磁&#xff1a;当计算电磁学遇上人工智能&#xff0c;一场效率革命正在发生 引言 在6G通信、新能源汽车与高端芯片设计等领域&#xff0c;电磁仿真已成为不可或缺的“数字试验场”。然而&#xff0c;传统基于有限元&#xff08;FEM&#xff09;、时域有限差分&#xff08…...

软件系统规划步骤和可行性研究步骤

前者是系统开发初始阶段的宏观活动序列,后者则是规划阶段中的一项核心子任务。 一、软件系统规划步骤(典型过程) 系统规划通常属于软件生命周期的“项目立项与计划”阶段,常见步骤如下: 初步调查 识别项目机会、用户需求、业务痛点,明确系统建设的初步目标与范围。 问题…...

AI群演请就位—个人博客(一)

项目背景随着大语言模型能力的提升&#xff0c;AI在内容生成与互动体验中的应用日益广泛。传统互动叙事类产品&#xff08;如互动小说、角色扮演游戏&#xff09;主要依赖预设脚本与有限分支选择&#xff0c;存在剧情固化、重复体验感强、角色缺乏真实感等问题。大语言模型的出…...

C++零基础到工程实战(3.1):if语句、bool类型、算数逻辑比较运算符深入解析

目录 一、本节学习内容概要图 二、前言 三、if语句与逻辑判断 3.1 基础语法 &#xff08;1&#xff09;if 条件语句 &#xff08;2&#xff09;else if 与 else 3.2 常见错误 &#xff08;1&#xff09;多余分号导致逻辑块独立 &#xff08;2&#xff09;判断时误写赋…...