网上乱七八糟的答案太多了,这里从直观感受和数学方法上对这块知识做了个整理,数学方法基于stackoverflow上的答案,补充了些推导细节方便理解。(内容比较精简,后续有时间整理下放到个人博客下)
HashMap是用来快速查找内容的一种数据结构。使用n个桶存储数据,数据具体存储在哪个桶中是由Hash算法决定的,即对原始内容执行Hash后得出对应桶的序号。
然后这种数据结构会遇到一些问题,由于内存空间有限,所以桶的数量也是有限制的。当桶的数量较小时就容易出现较多内容放在同一个桶中的情况。HashMap中使用默认的0.75作为桶空间的阈值,如果超过这个大小就需要增加桶的数量,以防止较多内容聚集在相同的桶中。
关于为什么0.75就是经常被拿来当做面试问题了。首先通过人脑直观来考虑这个事情,假设我现在有n个桶,那么数据放到多少我需要增加更多的桶呢。这个时候会出现直观的数字0.5,如果桶已经装满一半了那么之后添加内容分配到空桶的概率会低于分配到有内容桶的概率,可想而知从这个点之后将会出现越来越多的内容在相同的桶中。从这里来看这个0.5是个非常优秀的数字它是一个趋势的转折点。
但是这个0.5和负载因子是不一样的,这个0.5我们是指已经有一半的桶被占用了,而HashMap中的负载因子与我们存入的数据总数量相关,并且根据之前对这种数据结构的了解,数据会存在一定概率出现在一个桶中,所以当一半桶都被占用的时候我们实际存储的数据数量是大于0.5n的。
这里假设对于新的内容分配到各个桶的概率是相同的,当前内容数据大小为s。这里使用二项分布的概念,当我们进行了s次插入操作(实验),那么序号0的桶是空桶的概率是多少呢。即:
可以明显看出来当s增加P(0)是空桶的概率也会下降,这里用1/2来计算这个分界。即:
然后算下负载因子f=(s/n)对n取极限:
为了解决这个问题可以先解决这个问题:
我们得到的结果就是上面式子的倒数即e,把log换成ln即得出我们的负载因子界限值,这个值约等于0.6931,所以0.75的取值范围是与这个界限相近的并且由于基础是16个容量空间,使用0.75也不会算出小数是一个不错的值选取。
网友评论