HashMap几乎是面试必问的知识,对于HashMap面试是你真的能从容面对吗?相信如果你去面试知名互联网公司的时候,决对不会只是问问你HashMap的数据结构这么简单的问题。我收集了最近老大在面试过程中关于HashMap常问的几个问题:
1。为什么HashMap是2的幂次方?
<代码>新HashMap(14); 代码>
HashMap是由数组+链表(1.8还有红黑树)来实现的,那么上面这行代码它执行后,创建的数组大小是多少呢?
追踪源码可以看到它会执行这样一个函数来返回数组大小的:
<代码>静态最终int tableSizeFor (int帽){ int (n=帽- 1; |=n祝辞祝辞祝辞1; |=n祝辞祝辞祝辞2; |=n祝辞祝辞祝辞4; |=n祝辞祝辞祝辞8; |=n祝辞祝辞祝辞16; 返回(n & lt;0)?1:(n祝辞=MAXIMUM_CAPACITY) ?MAXIMUM_CAPACITY: n + 1; }代码>
-
<李>长度是2 ^ n - 1的话,可以保证,的结果是在哈希表的大小范围内,李>
<李>,运算与%取模的结果可以保证一致,李>
2。为什么HashMap的扩容因子是0.75 ?
加载因子是非常重要的一块,如果加载因子太大,假如为1,那么从空间利用率倒是上去了,但是时间效率就降低了。
如果加载因子太小,倒导致hashmap频繁的扩容操作,每次扩容都非常耗性能,
好吧!说了就像没说一样,关于这个问题我也只能抛砖引玉,
其实是这样的:
<代码>因为TreeNodes两倍大小的普通节点,我们 *使用alt=" HashMap你了解多少">4。jdk1.8扩容时会产生死循环吗?
<代码> NodeloHead=null, loTail=零; Node hiHead=null, hiTail=零; Node 下一个; {做 下一个=e.next; 如果(e。散列,oldCap)==0) { 如果(loTail==null) loHead=e; 其他的 loTail。下一个=e; loTail=e; } 其他{ 如果(hiTail==null) hiHead=e; 其他的 hiTail。下一个=e; hiTail=e; } },(下)(e=!=null); 如果(loTail !=null) { loTail。下一个=零; 打开[j]=loHead; } 如果(hiTail !=null) { hiTail。下一个=零; 打开[j + oldCap]=hiHead; }代码> 看下方图文分析:
所以,jdk1.8中的HashMap在扩容时就不会产生死锁了!
5。为什么是链表长度达到8时转为红黑树?
首先,TreeNode节点的占用空间的大小是链表节点的两倍,只有当容器达到8的时候才转为红黑树,为什么是8呢,在第二个问题中已经说明了,根据泊松分布可以看的出,链表节点是很难达到长度为8的时候的,如果真有特殊情况达到8了,那么才将链表转为红黑树;
转为红黑树时还有个要求,就是hashMap中的元素个数达到64。6。jdk1.8 HashMap是线程安全的吗?
JDK1.8HashMap虽然能够尽大的避免扩容时死循环问题,但是,HashMap仍然是线程不安全的,例如:线程在把元素时,线程B进行扩容;
之所以不安全的原因是多线程会操作同一实例变化,导致变量状态不一致。HashMap你了解多少