1、引出问题

- null是什么意思?
- map.size为什么是3?

数组大于64,或者链表大于8,才会变为红黑树
- 1.主数组长度?
- 2.主数组类型?
- 3.哈希码怎么计算的?
- 4.公式是什么?
- 5.节点在主数组中的位置?
- 6.节点的数据类型?
1.1 HashMap的底层数据结构?
在JDK1.7 中,由“数组+链表”组成,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的。“头插法”
在JDK1.8 中,由“数组+链表+红黑树”组成。尾插法。当链表过长,则会严重影响 HashMap 的性能,红黑树搜索时间复杂度是 O(logn),而链表是糟糕的 O(n)。因此,JDK1.8 对数据结构做了进一步的优化,引入了红黑树,链表和红黑树在达到一定条件会进行转换:
- 当链表超过 8 且数据总量超过 64 才会转红黑树。
- 将链表转换成红黑树前会判断,如果当前数组的长度小于64,那么会选择先进行数组扩容,而不是转换为红黑树,以减少搜索时间。
JDK1.8 后采用数组+链表+红黑树的数据结构。通过put和get存储和获取对象。当我们给put()方法传递键和值时,先对键做一个hashCode()的计算,来得到它在bucket数组中的位置来存储Entry对象。当获取对象时,通过get获取到bucket的位置,再通过键对象的equals()方法找到正确的键值对,然后在返回值对象。
1.2 为什么引入红黑树?
JDK 1.8 以前 HashMap 的实现是 数组+链表,即使哈希函数取得再好,也很难达到元素百分百均匀分布。当
HashMap 中有大量的元素都存放到同一个桶中时,这个桶下有一条长长的链表,这个时候 HashMap 就相当于一个单链表,假如单链表有 n 个元素,遍历的时间复杂度就是 O(n),完全失去了它的优势。
针对这种情况,JDK 1.8 中引入了 红黑树(查找时间复杂度为 O(logn))来优化这个问题。
而引入红黑树,就是为了提高查找效率的;因为红黑树是一种自平衡的二叉查找树;
这是HashMap解决查询效率低下的一种方式,还有一种方式是通过负载因子控制的扩容,每次Hash碰撞达到负载因子的时候,就会触发扩容,扩容为之前的两倍,从而大幅提高查找的效率;理论上扩容最高可以提升2倍的效率,但实际很难出现;

HashMap是一种常用的数据结构,基于数组+链表/红黑树实现。在JDK1.8中,当链表长度超过8且数组长度超过64时,链表会转换为红黑树以优化查找效率。HashMap的put方法包括计算hash值、解决冲突、扩容等步骤。在解决哈希冲突时,先使用链表,当节点数过多时转为红黑树。初始容量为16,负载因子为0.75,当元素达到容量的75%时会扩容。HashMap是非线程安全的,线程安全的替代品有HashTable和ConcurrentHashMap。

4360

被折叠的 条评论
为什么被折叠?



