HashMap知识总结


问题1:你知道HashMap底层的数据结构是什么吗?

JDK1.7的时候使用的是数组+ 单链表的数据结构。但是在JDK1.8及之后时,使用的是数组+链表+红黑树的数据结构(当链表的深度达到8时,也就是默认阈值,会自动扩容,把链表转换成红黑树的数据结构,同时时间复杂度由O(N)–》O(logN))

问题2:1.7和1.8有哪些区别

  1. 数据结构方面的不同,JDK1.7的时候使用的是数组+ 单链表的数据结构。但是在JDK1.8及之后时,使用的是数组+链表+红黑树的数据结构
  2. 数据插入的变化。JDK1.7用的是头插法,而JDK1.8及之后使用的都是尾插法由于数据结构方面的变化,为啥做这样的优化?这是因为jdk1.7是用单链表进行的纵向延伸,采用头插法容易出现逆序环形链表死循环的问题,而在jdk1.8由于数据结构采用红黑树,使用尾插法可以避免出现环形链表死循环的问题

问题3:JDK_1.8中对hash算法和寻址算法是如何优化的

hash算法的优化:对每一个hash值,在它的低16位中,让高低16位进行异或,让它的低16位同时保持了高低16位的特征,这样可以尽量避免一些hash值后续出现冲突,进入到数组中的同一个位置。
寻址算法的优化:用与运算代替了取模运算–》即拿hash值跟数组长度减一做与运算

问题4:你知道HashMap是如何解决hash碰撞问题的吗?

1) 什么是hash碰撞问题?

就是指两个key 或者多个key,他们算出来的hash值,与n-1 与 运算之后,发现定位出来的数组的位置还是一样的,hash碰撞,

2) hash冲突 那怎么来解决的呢?

jdk1.8前是在这个数组位置挂一个链表,让多个key-value对,同时放在数组的一个位置里,然后get的时候,如果定位到数组发现挂了一个链表,此时遍历链表,从里面找到自己要找的那个key-value对即可。
但是假设你的链表很长,可能会导致遍历链表性能会比较差。而jdk1.8做了些优化,如果链表的长度达到了一定的长度,会把链表转换为红黑树

问题5:说说HashMap是如何进行扩容的可以吗?

1)什么时候进行扩容?

当存储的容量达到了负载因子的75%就会进行扩容

2)怎么样进行扩容?

  1. 创建一个新的entry数组,长度为原来2倍;
  2. 进行ReHash操作,遍历原来的entry数组,将原有的entry重新hash到新数组

3)hashmap的初始长度是多少?

是16,为啥是16,因为在底层源码里定义了位运算1>>4 -->16,这是为了服务key映射到index的算法.

问题6: 那hashcode和equals在hashmap中是怎么用的?

  1. 首先hashmap是通过key的hashcode方法来寻找index,那如果两个key找到的index相同,那么他们就在一个链表上面,比如 “AB” 和 “BA” 可能index都为2,这样她们就在一个链表上面
  2. 这个时候怎么来找 “AB” 和 “BA” 对应的具体的值呢?就是通过equals,,就是说对equals重写,保证相同的对象返回相同的hash值,不同的对象返回不同的hash值

猜你喜欢

转载自blog.csdn.net/m0_37900506/article/details/113919635