社招必备!HashMap的put方法底层揭秘,面试官都说赞!

软件求生 2024-12-28 09:28:33

 Hello 大家好!我是小米,一个积极分享技术的小伙伴,今天我们继续聊聊 Java 面试中的热门话题——HashMap 的 put 方法的具体流程。这是一个老生常谈的面试题,但很多人了解得不够深入,导致在面试时只能泛泛而谈。今天我们通过一个生动的小故事,来剖析一下它的底层原理,希望大家看完后能对它了然于心!

故事背景:HashMap 的大冒险 在一个神秘的「Java 集合世界」中,有一座巨大的宫殿,这就是 HashMap。它负责存储和管理这个世界中的各种「钥匙-宝藏(key-value)」对。 一天,一个叫作「put 方法」的小勇士接到了任务:把一件新的「钥匙-宝藏」对送进 HashMap 的宫殿。 冒险开始:put 方法的具体流程 第一步:勇士探路——检查钥匙的合法性 put 方法的小勇士,首先检查了任务交给他的钥匙(key)。他要确保钥匙不能是 null,否则会很麻烦。不过,HashMap 的设计师考虑周到,允许存储一个特殊的 null 键,并将它放在宫殿的「入口大厅」(bucket[0])。 代码片段:

第二步:钥匙定位——计算哈希值 接着,小勇士需要找到钥匙在宫殿中的具体位置。他通过钥匙的 hashCode() 方法,计算出一个哈希值(hash value)。不过,为了避免直接使用 hashCode 导致的分布不均,他会对哈希值进行一番加工。 代码片段:

这个加工方法通常是对 hash 值进行高位运算,以增强分布随机性。具体实现如下:

第三步:选择房间——定位到桶(bucket) 计算出哈希值后,小勇士根据宫殿的总房间数(即数组容量)找到对应的房间(bucket)。这个过程是通过对数组长度取模来完成的。 代码片段:

第四步:探查房间——查找链表或树结构 找到房间后,小勇士进入房间查看。房间可能是空的,也可能存放着一堆钥匙-宝藏对。为了确保钥匙的唯一性,他会在房间中查找是否已经存在相同的钥匙。 如果房间里是链表结构,小勇士会遍历每一个节点,比较 key.equals()。 如果房间里是红黑树,小勇士会用树的查找规则寻找相应节点。 代码片段:

插入的精彩瞬间:链表转红黑树 HashMap 的宫殿设计师不仅考虑到了普通情况下的性能,还特别设计了一项优化:当房间里的链表节点数量超过阈值(默认是 8)时,链表会升级为红黑树。这大大提升了在大量数据下的查找效率。 代码片段:

第五步:存储宝藏——添加节点 如果房间里没有相同的钥匙,小勇士会在房间里新增一个节点来存储新的钥匙-宝藏对。 代码片段:

这里的 Node 是 HashMap 的一个静态内部类,它封装了 key、value 以及指向下一个节点的指针(用于形成链表)。 第六步:扩展宫殿——检查容量 任务完成后,小勇士还有一个重要的责任——检查宫殿是否需要扩建。如果宫殿的负载因子(load factor)超过阈值(默认是 0.75),他就会触发扩容操作。 扩容的过程很有趣,它会创建一个新的宫殿,容量是当前的两倍,然后重新分配所有钥匙-宝藏对的位置。 代码片段:

完整流程总结 从钥匙检查到定位再到存储,put 方法的工作流程可以总结为以下几步: 检查 key 是否为 null。 计算 hash 值并定位桶。 遍历桶中的链表或树结构,检查是否有相同的 key。 如果有相同的 key,则更新对应的 value;否则,创建新的节点插入。 检查负载因子,必要时进行扩容。 面试中如何回答? 当面试官问到「HashMap 的 put 方法的具体流程」时,可以从以下几个方面展开: 大体流程:概述 put 方法的整体逻辑。 细节补充:强调 hash 值计算、链表到红黑树的转换、扩容等核心细节。 性能优化:分析 HashMap 的时间复杂度(插入、查询的均摊复杂度是 O(1))以及在极端情况下可能退化为 O(n) 的原因。 END HashMap 的设计精妙且高效,理解它的底层实现不仅对面试有帮助,也能帮助我们写出更高效的代码。希望今天的小故事能让大家对 put 方法有更深刻的认识! 如果你觉得这篇文章对你有帮助,记得点个「在看」或者分享给你的朋友!如果还有其他想了解的话题,欢迎留言告诉我!我们下期再见啦~ 我是小米,一个喜欢分享技术的29岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!

0 阅读:0
软件求生

软件求生

从事软件开发,分享“技术”、“运营”、“产品”等。