面试烂的hashMap你真的懂吗?

前言:HashMap是java工程师在面试过程中,碰到的概率极大的一道题,很大一部分人都是看了一些博客,记住一些答案,但是深究往往无法接招,本文就来扒一扒hashMap面试常见的点及源码分析。

推荐分析目前为止个人看过的分析hashMap比较好的文章。
Java 8系列之重新认识HashMap
没有阅读过的同学,可以先看一下这篇文章,对于hashMap的设计及原理有一个大概的了解,一遍不行;读两遍。

1、hashMap中提到了“当链表长度大于8时,链表默认转化为红黑树”,为什么链表长度为8的时候转化呢?

答:如果节点数量比较少遍历链表速度也很快,没必要转成树,而且树还要多占空间,那么如何定一个临界值呢?根据泊松分布节点相同次数超过8个节点的概率大概是百万分之一,再记录增加概率也不会降低太多,最终得到一个临界值是8,也就是说插入到hashMap中节点,真正需要转化为红黑树的其实是很少的情况。

我们可以看一下源码做的统计:

	*
	* 0:    0.60653066
	* 1:    0.30326533
	* 2:    0.07581633
	* 3:    0.01263606
	* 4:    0.00157952
	* 5:    0.00015795
	* 6:    0.00001316
	* 7:    0.00000094
	* 8:    0.00000006
	* more: less than 1 in ten million
	*

2、我们知道随着同一个槽中节点的减少,红黑树可能会退化成链表,jdk中定义了该值为6,为什么定义为6,而不是7呢?

/**
  * 当红黑树元素个数小于6的时候,会从新退化为链表。为什么?效率。
  */
static final int UNTREEIFY_THRESHOLD = 6;

答:链表查找的时间复杂度=O(n/2)O(n/2),红黑树的查找时间复杂度是O(logn)O(logn),当n=8,红黑树的时间是2,链表的时间是4,红黑树优于链表。当n=6,链表查询时间是3,红黑树是2.585,红黑树基本已经没什么优势了,其实对于7也没什么优势,但是如果选择7会导致链化和树化频繁切换,所以间隔调两个元素。5、6同理,但是总得敲定一个数呀。

3、为什么hashMap在扩容的时候,容量大小必须是2n2^n呢?
HashMap采用这种非常规设计,主要是为了在取模和扩容时做优化,同时为了减少冲突,HashMap定位哈希桶索引位置时,也加入了高位参与运算的过程。
扩容的时候,可以做到元素的新位置要么是在原位置,要么是在原位置再移动2次幂的位置
hash值新增的那个bit是1还是0就好了,是0的话索引没变,是1的话索引变成“原索引+oldCap”

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章