1. 计算键的哈希值:
对于给定的键,通过键的`hashCode()`方法计算出一个哈希值。这个哈希值将用于确定键值对在哈希表中的存储位置。
2. 确定存储位置:
通过对哈希值进行运算(通常是取模操作,与哈希表的容量减一进行与操作,也就是和底层数组的长度做取模运算),得到在哈希表中的索引位置。这个位置就是键值对可能存储的位置。
3. 处理冲突:
如果计算得到的位置已经有其他键值对存在(发生了冲突),则需要进行冲突处理。`HashMap`通常使用链表法或红黑树来处理冲突。jdk1.8之前采用链表,新添加的元素会采用头插法放在链表头部,jdk1.8之后采用链表和红黑树,新添加的元素采用尾插法,放在链表末尾,如果这个链表长度超过默认值8就会转为红黑树结构
4. 添加键值对:
如果计算得到的位置为空,直接将新的键值对存储在该位置。 如果该位置已经存在相同的键,则更新对应的值。
5. 可能的扩容操作:
在添加键值对的过程中,如果哈希表的大小超过了负载因子(负载因子可以简单理解为一个比值,例如现在负载因子是0.5,底层数组长度是6,两者乘积就是3,也就是说长度超过3就扩容)与当前容量的乘积,`HashMap`会进行扩容操作。 扩容意味着创建一个更大的数组,并将现有的键值对重新哈希到新的数组中。 总的来说,`HashMap`的`put`方法通过哈希函数确定键值对的存储位置,并处理可能的冲突和扩容情况,以高效地存储和检索键值对。