在Java中,对于HashMap这样的实现,put
方法是用来将一个键值对插入到Map中的核心方法。以下是HashMap类中put
方法的大致执行流程:
- 计算Hash值:
- 首先,
put
方法会接收一个键(Key)和一个值(Value)作为参数。 - 调用键对象的
hashCode()
方法得到一个哈希码(hash code)。 - 这个哈希码通常会通过某种散列函数进一步处理,以便均匀分布到HashMap内部的数组中。在HashMap中,会使用
(n - 1) & hash
这样的运算来确定数组的索引位置,其中n
是数组的长度。
- 首先,
- 解决哈希冲突:
- 如果目标数组索引位置上已经存在元素(即发生了哈希冲突),则会检查是否存在链表(或树形结构,在Java 8中引入了红黑树来优化链表过长的情况)。
- 如果是链表结构,则遍历链表,通过
equals()
方法来查找是否有相同的键。如果有,则更新该位置上的键对应的值。 - 如果遍历结束后都没有找到相同的键,则会在链表末尾(或树形结构的相应位置)新增一个包含新键值对的节点。
- 扩容(Resize):
- 在插入新元素之前或之后(取决于具体实现),HashMap可能需要检查是否需要扩容。当Map中的元素数量超过一定的阈值(通常是容量的一定比例,默认负载因子为0.75)时,HashMap会创建一个新的更大的数组,并将所有旧的键值对重新哈希到新的数组中,这一过程称为“扩容”或“rehash”。
- 插入新元素:
- 如果目标位置上没有冲突或冲突已解决,则直接在该位置上插入新的键值对节点。
- 调整大小:
- 插入新元素后,如果触发了扩容操作,还会相应调整HashMap的容量和阈值,以适应更多的键值对。
Java的Mapput
方法涉及到了哈希计算、冲突解决、可能的扩容操作,最终确保键值对被正确地插入到Map中。整个过程设计的目标是为了尽可能快速地进行查找、插入和删除操作,并保持较好的空间效率。
- 插入新元素后,如果触发了扩容操作,还会相应调整HashMap的容量和阈值,以适应更多的键值对。
HashMap添加数据的详细过程,如下图: