- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
HashMap高频面试题及参考答案
一、基础原理类
问题:HashMap的底层数据结构是什么?JDK1.7和1.8有什么区别?
答案:JDK1.7底层是“数组+链表”,数组是主体,链表用于解决哈希冲突(拉链法);JDK1.8优化为“数组+链表+红黑树”,当链表长度超过8且数组容量≥64时,链表会转为红黑树,目的是提升查询效率(链表查询时间复杂度O(n),红黑树O(logn))。另外1.7扩容时会重新计算哈希值,1.8直接用原哈希值高位参与运算,减少哈希冲突。
问题:HashMap的哈希函数是怎么设计的?为什么这么做?
答案:哈希函数流程是“取key的hashCode()得到int值→高位无符号右移16位→与原hashCode异或运算→对数组长度取模(h(length-1))”。这么设计有两个原因:一是高位参与运算能减少哈希冲突(避免只用到低位导致的冲突);二是用“与运算”替代“取模”,因为数组长度是2的幂次时,h(length-1)等价于h%length,但位运算效率更高。
问题:HashMap的key可以为null吗?value呢?底层怎么处理nullkey?
答案:key和value都可以为null。底层对nullkey的处理是固定哈希值为0,直接存到数组索引0的位置(如果该位置已有元素,就加到对应的链表/红黑树中)。注意Hashtable的key和value都不能为null,这是两者的重要区别。
二、扩容与阈值类
问题:HashMap的初始容量、负载因子是什么?扩容的触发条件是什么?
答案:初始容量默认是16(必须是2的幂次),负载因子默认0.75。扩容触发条件是“当前元素个数(size)≥阈值(threshold)”,而阈值=容量×负载因子。比如初始时阈值=16×0.75=12,当存入第13个元素时,就会触发扩容,扩容后的容量是原容量的2倍(保证还是2的幂次)。
问题:为什么HashMap的容量必须是2的幂次?
答案:核心是为了让“h(length-1)”等价于“h%length”,同时提升运算效率。如果容量是2的幂次,length-1的二进制会是“000...111”的形式,与哈希值进行与运算时,能均匀保留哈希值的低位,减少哈希冲突;如果容量不是2的幂次,length-1的二进制会有0的位,导致部分索引永远无法被访问,哈希冲突加剧,数组空间利用率降低。
问题:JDK1.8中,HashMap扩容时元素的迁移逻辑是什么?
答案:1.8不再像1.7那样重新计算每个元素的哈希值,而是根据元素原哈希值的“高位是否为1”来判断新索引:如果高位是0,新索引=原索引;如果高位是1,新索引=原索引+原容量。这样迁移时无需重新哈希,效率更高,而且能保证原链表中的元素均匀分散到新数组的两个位置,避免链表过长。
三、线程安全与对比类
问题:HashMap是线程安全的吗?如果不是,有什么线程安全的替代方案?
答案:HashMap不是线程安全的。在多线程环境下,并发修改(比如同时put、扩容)可能导致链表成环(JDK1.7)、数据丢失、死循环等问题。线程安全的替代方案有:①Hashtable:直接在方法上加synchronized,效率较低;②ConcurrentHashMap:JDK1.7用分段锁,JDK1.8用CAS+synchronized,效率比Hashtable高,支持并发操作;③用Collections.synchronizedMap(newHashMap()):包装成线程安全类,本质是给所有方法加锁,效率一般。
问题:HashMap和ConcurrentHashMap的核心区别是什么?
答案:①线程安全:HashMap非线程安全,ConcurrentHashMap线程安全;②实现方式:HashMap是“数组+链表+红黑树”,ConcurrentHashMap1.7是“分段数组+分段锁+链表”,1.8是“数组+链表+红黑树+CAS+synchronized”;③功能支持:ConcurrentHashMap不允许key或value为null,HashMap允许;④效率:ConcurrentHashMap支持并发读写,锁粒度更细(1.8是节点级锁),效率远高于Hashtable,也比Collections.synchronizedMap高;⑤迭代器:Ha
原创力文档


文档评论(0)