Map (二) HashMap put()方法详细解刨

本文详细剖析了HashMap的put()方法在不同场景下的操作,包括数组未初始化、键值对不存在、键相等、键不相等、多个键值对存在但键相同或不同,以及链表转红黑树的情况。每个场景都涵盖了存储和覆盖的逻辑,并提到了当容量超过特定阈值时的扩容操作。

创建 HashMap 我们的即可开始往里面存键值对啦。我们来一步一步的看看 HashMap 是如何存储!

我们要模拟一下存储时的多种场景,后场景是在前场景不匹配的情况下的场景(如有遗漏请评论提醒):

我们先理解3个主要参数:

  • hash (通过 key 计算出的 int 值)
  • key (传入的 key)
  • value (传入的 value)

我们模拟 hash 计算结果是每个场景下都存入的到坐标为 0 的 Node数组中。
先粗略的看一下各个场景是如何做到值的添加和覆盖,最后附上源码详细流程:

场景1:存储时 HashMap 的 Node 数组未初始化

这里写图片描述

场景2:当前坐标下不存在值

这里写图片描述

场景3:当前坐标下只有一个值并且存储的 key 相等

这里写图片描述

场景4:当前坐标下只有一个值并且存储的 key 不相等

HashMap 的 `put` 方法用于向哈希表中插入或更新键值对,其主要步骤如下: 1. **计算哈希值**:在 `put` 方法调用时,首先会对传入的键 `key` 计算哈希值。在 Java 代码中,`put` 方法调用了 `putVal` 方法并传入了 `hash(key)` 的结果,即 `public V put(K key, V value) { return putVal(hash(key), key, value, false, true); }`,这里的 `hash(key)` 就是在计算键的哈希值,以此来确定该键值对在哈希表中的大致位置 [^1]。 2. **定位桶位置**:根据计算得到的哈希值,确定该键值对应该存放在哈希表的哪个桶(数组位置)中。这是哈希表存储数据的基础,通过哈希值映射到具体的数组索引位置。 3. **处理冲突**:如果该桶位置已经有其他键值对存在(即发生哈希冲突),就需要进行冲突处理。常见的冲突处理方式有链表法和红黑树法。当链表长度达到一定阈值(通常为 8)且数组长度达到 64 时,链表会转换为红黑树,以提高查找效率。 4. **插入或更新键值对**:如果桶为空,直接将新的键值对插入该桶;如果桶不为空且键已存在,则更新该键对应的值;如果键不存在,则将新的键值对添加到链表或红黑树中。 5. **检查是否需要扩容**:在插入键值对后,会检查当前哈希表的元素数量是否达到了扩容阈值(负载因子 * 数组长度)。如果达到了阈值,就会对哈希表进行扩容操作,一般是将数组长度扩大为原来的 2 倍,并重新计算所有键值对的位置,将它们分配到新的桶中 [^3]。 ### 相关代码示例 ```java import java.util.HashMap; public class HashMapPutExample { public static void main(String[] args) { HashMap<String, Integer> map = new HashMap<>(); // 调用 put 方法插入键值对 map.put("one", 1); map.put("two", 2); map.put("three", 3); } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值