【HashMap 底层,put、get流程、怎么哈希、什么时候转红黑树、为什么红黑树阈值是8不是6或者10】

HashMap 是 Java 中常用的一种 Map 实现,其底层数据结构是数组加链表(或红黑树),通过哈希算法实现快速的查找和插入操作。

put 流程

首先,计算 key 的哈希值;
根据哈希值找到数组中的对应位置,如果该位置没有元素则直接插入,插入后判断当前数组大小是否超过了负载因子,如果超过了则进行扩容;
如果该位置已经存在元素,则需要进行链表或者红黑树的插入操作,如果链表长度超过了阈值(默认为 8),则需要进行链表转红黑树的操作;
如果插入的 key 已经存在,直接更新 value 即可。

get 流程

计算 key 的哈希值;
根据哈希值找到数组中对应的位置,如果该位置没有元素则返回 null;
如果该位置有元素,则需要判断是链表还是红黑树,如果是链表则顺序遍历查找,如果是红黑树则通过红黑树的查找算法查找;
如果找到了对应的元素,则返回其 value 值。

哈希算法

HashMap 内部采用了哈希算法来确定元素在数组中的位置,其实现方法是将 key 的 hashCode() 方法返回的值进行一系列的处理,最终得到在数组中的下标。
具体实现方法是通过 hash() 方法将 key 的哈希值与数组长度进行取模运算,得到在数组中的位置。hash() 方法的实现是为了尽量避免哈希冲突,减少链表长度。

何时转红黑树

默认情况下,当链表长度超过 8 时,会将链表转化为红黑树。这是因为当链表长度过长时,会影响到 HashMap 的性能。红黑树相对于链表可以更快地进行查找、插入、删除操作,提升了 HashMap 的性能。

为什么阈值是 8 而不是 6 或 10 呢?这是因为在实际应用中,链表的长度一般不会超过 8,大部分情况下都是在 2 ~ 4 的范围内。因此,将阈值设为 8 可以在大部分情况下保证 HashMap 的性能。同时,阈值也不能太小,否则可能会导致过早地将链表转化为红黑树,增加了额外的开销。