以下面试题从看准,牛客,以及大量大厂面经中收集而来,面向真实面试。
一、面试题总览
面试题整理后分为三大模块,分别是数据结构,扩容以及线程安全,同样梳理HashMap的时候也可以从这三个角度展开。下面这些问题相信大家在面试过程中也会被经常问到,也很容易的回答出来。就我本身而言,每次面试的时候都会重新看一遍源代码,有时候还回去再找一些相应的题目,这其实浪费了很多时间,所以我想把这些都整理出来,供大家和自己复习,以后面试过程中使用。如果其中有什么问题,欢迎指正,留言交流,非常感谢。
1.数据结构
HashMap面试题
1.hashmap的数组长度为什么要保证是2的幂?(Hash表设计文章中已解答)
性能及空间利用率两点来回答。
位运算性能较取模运算快,其实可以不一定是2的幂,但这样会导致利用率较低。比如15,最后一位永远是0,任意hash值与其做与运算得到的索引永远是偶数,这样就会导致只有一半的利用率。所以为2的幂才是最合适的。
2.hashmap如何解决hash冲突? 以及如果冲突了,怎么在hash表中找到目标值
链地址法以及红黑树。扩容
如果并没有达到树化条件,则直接扩容
判断是否产生冲突
判断是否为树
插入到链表尾部后,判断是否要进行树化。
首先计算hash值,定位桶位,判断桶中元素类型是Node还是TreeNode,如果是Node表明是链表,如果是TreeNode为红黑树结构,链表直接遍历,红黑树直接查找。
3.怎么尽量避免哈希冲突,自己说了充分利用对象的属性+良好的哈希算法,但是面试官还继续追问,自己好像也没有找到答案,扩容??
4遇到哈希冲突的时候,除了数组+链表,还有什么处理方式
5.hashMap底层?为什么jdk1.8要用红黑树实现?什么时候会出现线程不安全?怎么解决线程不安全?默认初始容量是16,如果我改成7,容量会变成7么?为什么?
6.为什么hashmap中的链表需要转成红黑树?
7.jdk1.8之前并发操作hashmap时为什么会有死循环的问题?
由于前面确定了负载因子为0.75,在loadfactor为0.75时根据泊松分布,
8.HashMap 转成红黑树,8这个数字是怎么来的 泊松分布;退化为链表的6这个数字呢?
9.loadFactor为什么是0.75?
10.上来问项目,然后问hashmap每一步都问,印象最深的是为什么计算hash值要右移16位不是17位。还有设计原则。当时没背。凉凉
11.往HashMap插入删除数据,时间复杂度是多少
12.红黑树和链表那个增加快
13.怎么实现HashMap,定义需要的方法和API,时间复杂度不能为O(n)
14.HashMap 1.7为什么会导致死循环?
15.有1000个数据存在hashmap中,实际的数量是多少,考虑负载因子和扩容
16.Hashmap为什么不用平衡树?为什么用红黑树而不是B树,B+树,AVL树
17.HashMap HashTable区别 HashMap的优化
18.你都知道哪些Map,都在什么场景下使用?为什么?
19.hashmap为什么要重写hashcode和equls方法
20.说一说jdk1.8中,对hashMap的优化
21.红黑树和AVL树有什么区别?HashMap为什么不采用AVL树?
22.如何能提示HashMap的性能
预设hashmap的长度,避免resize,这也是问当确定了数据总量为1000,数组总长度应该是多少的原因
23.HashMap key可以为null,为什么ConcurrentHashMap key 不可以为null ?
ConcurrentHashMap不能为null原因,无法去判断到底是key不存在还是value为null
24.hashmap初始大小 1>4 = 16;最大 1>30 即2的30次方;超过最大值如何处理?
25.resize是否要重新计算hash值?
26.java hashMap和redis map的rehash有什么区别?
27.HashMap 如何保证容量一直是2的N次方,如果构造函数传的不是2的n次方呢?
28.JAVA8 的 HashMap 中 TREEIFY_THRESHOLD 常量为什么是 8 ?https://www.v2ex.com/t/651978
29.HashMap节点是有序的吗?了解哪些有序的Map?
HashSet面试题
1.HashSet的value是什么
2.HashSet为什么不存null?
hashMap的put方法,返回null表示新添加,返回oldValue表示覆盖。
2.扩容
1.hashmap什么时候会触发扩容?
2.hashmap扩容时每个entry需要再计算一次hash吗?
3.说一下hashmap的扩容机制吧
3.线程安全问题
1.java hashMap和redis map的rehash有什么区别?
2.如何才能得到一个线程安全的HashMap?
下面从源码的角度来分析和解答以上问题。
二、HashMap源码分析
版本JDK1.8,后面会分析JDK1.7中HashMap源码
1.默认数据
//默认初始容量16static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; //最大容量2^30static final int MAXIMUM_CAPACITY = 1 << 30;//默认负载因子 0.75static final float DEFAULT_LOAD_FACTOR = 0.75f;//需要树化的链表长度阈值static