- hahmap数据结构
JDK1.7中,HashMap采用位桶+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低;
JDK1.8中,HashMap采用位桶+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间
- HashMap中CRUD操作的底层实现原理是什么?
PUT
1. 通过key计算出一个hashcode
2. 通过hashcode与“与操作”计算出一个数组下标
3. 在把put进来的key,value封装为一个entry对象
4. 判断数组下标对应的位置,是不是空,如果是空则把entry直接存在该数组位
置
5. 如果该下标对应的位置不为空,则需要把entry插入到链表中
6. 并且还需要判断该链表中是否存在相同的key,如果存在,则更新value
7. 如果是JDK7,则使用头插法;如果是JDK8,则会遍历链表,并且在遍历链表的过程中,统计当前链表的元素个数,如果超过8个,则先把链表转变为红黑树,并且把元素插入到红黑树中
头插法:冲突的时候,将后面插入的元素放到链表的头部;
GET
- JDK8中链表转变为红黑树的条件?
1. 链表中的元素的个数为8个或超过8个
2. 同时,还要满足当前数组的长度大于或等于64才会把链表转变为红黑树。为什么?因为链表转变为红黑树的目的是为了解决链表过长,导致查询和插入效率慢的问题,而如果要解决这个问题,也可以通过数组扩容,把链表缩短也可以解决这个问题。所以在数组长度还不太长的情况,可以先通过数组扩容来解决链表过长的问题。
- hashMap中的hash()
在hashmap中要找到某个元素,需要根据key的hash值来求得对应数组中的位置。如何计算这个位置就是hash算法。
- 为什么HashMap的数组的大小是2的幂次方数?
数组大小为2的幂时hashmap访问的性能最高。
hash时采用了二进制的位运算来提高计算速度,而不是使用常规的取模;
- 在高并发大流量的情况下,hashMap有什么问题吗,会不会造成cpu达到100%?如果会,那是在哪一步可能会出现这个问题呢(插入、删除、查找、扩容)?
会造成,是在扩容的时候的头插法引起的
扩容前链表中元素顺序 :A---->B
扩容前链表中元素顺序 :B---->A
扩容为多步操作:数组扩容、元素转义,因此当多线程操作的时候,假如线程1完成了数组扩容,此时元素顺序 :A---->B,此时线程上下文切换;线程2完成了数组扩容、元素转义两步操作,链表中元素顺序 :B---->A。那么就会出现互相指向。
当链表数组的容量超过初始容量的0.75时,再散列将链表数组扩大2倍,把原链表数组的搬移到新的数组中。
参考文章:
HashMap与红黑树_Lin_Dong_Tian的博客-CSDN博客_hashmap红黑树
hashmap hash冲突怎么解决_HashMap原理_徐一僧的博客-CSDN博客
详解 HashMap 中的 hash 函数_得一的博客-CSDN博客_hash函数
为什么hashMap的容量扩容时一定是2的幂次_平凡之路无尽路的博客-CSDN博客_hashmap容量为什么是2的幂次