HashMap 是 Java 中常用的哈希表实现,它基于数组和链表(或红黑树)的组合实现。在 Java 8 中,当链表长度超过一定阈值时,HashMap 会将链表转换为红黑树,以提高查找、插入和删除操作的效率。
底层源码的简要介绍如下:
- 数组存储桶:HashMap 内部使用数组来存储键值对,称为桶(bucket)或节点(node)数组。每个桶可以存储一个或多个键值对。
- 链表:每个桶中的键值对以链表形式存储,即每个节点都包含键、值和指向下一个节点的引用。
- 红黑树:当链表长度超过阈值(默认为 8)时,HashMap 会将链表转换为红黑树。红黑树是一种自平衡二叉搜索树,它在大量元素存在时具有更好的性能。
- 哈希算法:HashMap 使用键的哈希码(通过键的
hashCode()方法获取)来确定键值对在数组中的位置。通过哈希函数将哈希码映射到桶的索引位置。 - 解决哈希冲突:当多个键具有相同的哈希码时,称为哈希冲突。HashMap 使用链表或红黑树来解决哈希冲突,通过比较键的值来确定具体的键值对。
红黑树和 B+ 树是不同类型的数据结构,它们在存储和查找方面有以下区别:
- 结构:红黑树是一种自平衡二叉搜索树,每个节点有两个子节点。B+ 树是一种多路搜索树,节点可以有多个子节点。
- 存储方式:红黑树的节点存储键和值。B+ 树只在叶子节点存储键和值,非叶子节点只存储键和指向子节点的引用。
- 应用场景:红黑树常用于需要高效的插入、删除和搜索操作的数据结构,如哈希表的链表转换。B+ 树常用于数据库和文件系统等需要范围查询和有序遍历的场景。
为什么 HashMap 选择红黑树作为链表的替代方案呢?这是因为红黑树相对于链表具有更好的查找、插入和删除性能。在链表中,这些操作的时间复杂度是 O(n),而在红黑树中,它们的时间复杂度是 O(log n)。因此,当链表长度超过阈值时,使用红黑树可以提高 HashMap 的性能。