- JDK1.8之前
- `HashMap` 底层是 数组和链表 结合在一起使用也就是 链表散列。HashMap 通过 key 的 hashCode 经过扰动函数处理过后得到 hash 值,然后通过 (n - 1) & hash 判断当前元素存放的位置(这里的 n 指的是数组的长度),如果当前位置存在元素的话,就判断该元素与要存入的元素的 hash 值以及 key 是否相同,如果相同的话,直接覆盖,不相同就通过拉链法解决冲突。
- 所谓扰动函数指的就是 HashMap 的 hash 方法。使用 hash 方法也就是扰动函数是为了防止一些实现比较差的 hashCode() 方法 换句话说使用扰动函数之后可以减少碰撞。
- JDK1.8及以后
- 相比于之前的版本, JDK1.8 之后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为 8)(将链表转换成红黑树前会判断,如果当前数组的长度小于 64,那么会选择先进行数组扩容,而不是转换为红黑树)时,将链表转化为红黑树,以减少搜索时间。
- TreeMap、TreeSet 以及 JDK1.8 之后的 HashMap 底层都用到了红黑树。红黑树就是为了解决二叉查找树的缺陷,因为二叉查找树在某些情况下会退化成一个线性结构。
最简回答:HashMap在JDK1.7使用的是数组+链表的结构,在哈希冲突时通过链表进行解决;而JDK1.8引入了红黑树的概念,当链表长度超过一定阈值时,链表会转换成红黑树,以提高查询效率。
HashMap为什么用红黑树不用B树
HashMap 使用红黑树(Red-Black Tree)而不是 B 树的主要原因是效率和复杂度。
- 效率:红黑树相对于 B 树,在插入、删除和查找操作上具有更好的平均性能。红黑树的平衡性质可以保证树的高度相对较小,从而减少了搜索的路径长度,提高了操作的效率。
- 复杂度:B 树是一种多路搜索树,节点可以包含多个关键字和指针,适合用于磁盘存储等场景,可优化磁盘 IO 操作。然而,在内存中的数据结构中,红黑树的实现更为简单,代码的复杂度较低。同时,红黑树的性能在典型的 HashMap 使用场景中通常表现出良好的性能。
另外,HashMap 维护了一个哈希表和一个链表或红黑树的混合结构(JDK8 之后),当发生哈希冲突时,会使用链表或红黑树来处理冲突。链表适合处理冲突较少的情况,而红黑树则适合处理冲突较多的情况。红黑树相对于链表具有更高的查找效率,因此在冲突较多的情况下能够提供更好的性能。
总之,HashMap 使用红黑树而不是 B 树主要是出于对效率和复杂度的考虑。红黑树在内存中的实现更简单,对于典型的 HashMap 使用场景能够提供良好的性能,且适用于处理冲突较多的情况。
最简回答:HashMap使用红黑树而不是B树,是因为红黑树相对于B树在插入、删除和查找等操作上的平衡性能更好,且红黑树的节点比B树的节点更小,占用的内存更少,适合存储在内存中的数据结构。