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碰撞达到负载因子的时