在Java 8中,HashMap的插入流程如下:
- 当你创建一个新的HashMap对象时,它内部会初始化一个默认的初始容量(一般为16)和加载因子(默认为0.75)。加载因子表示当HashMap中的元素数量达到容量的75%时,会自动触发扩容操作。
- 当你调用
put(key, value)方法将一个键值对插入到HashMap中时,首先会根据键的hashCode()方法计算出哈希码(hash code)。HashMap使用哈希码来确定键值对在内部数组中的位置。 - 接下来,HashMap会根据哈希码计算出数组的索引位置。具体计算方式是,将哈希码与当前数组的长度进行按位与(bitwise AND)运算,然后得到的结果作为索引。
- 如果该索引位置上没有其他键值对,那么将新的键值对直接插入到该位置。如果有冲突(即多个键值对哈希码计算后得到的索引位置相同),则会使用链表或红黑树来解决冲突。
- 在Java 8中,HashMap在解决冲突时采用的是链表的方式。具体做法是,在索引位置上的链表中遍历所有键值对的键,与要插入的键进行equals()比较。如果找到相同的键,则替换对应的值;如果没有找到相同的键,则在链表末尾添加新的键值对。
- 当链表中的键值对数量达到一定阈值(默认为8)时,链表会转换为红黑树。红黑树的插入操作比链表更高效,尤其是对于大量冲突的情况。
- 如果HashMap的元素数量达到了加载因子所规定的阈值(容量的75%),就会触发扩容操作。扩容会创建一个更大的数组,并重新将所有键值对插入到新的数组中。这个过程需要重新计算所有键的哈希码和索引位置。
总结起来,Java 8中HashMap的插入流程是:计算哈希码 -> 计算索引位置 -> 冲突解决(链表或红黑树) -> 扩容(如果需要)。
需要注意的是,Java 8之后的版本中,HashMap的实现发生了一些变化。在Java 8之前,HashMap使用的是数组+链表的结构来解决冲突,而在Java 8之后,当链表长度超过一定阈值时会转换为红黑树,以提高性能。