HashMap初始大小为什么是16 加载因子什么是0.75 扩容倍数为什么是2

众所周知HashMap添加数据的时候,是通过取模(取余)运算的,但为什么初始大小为16呢

先领大家看一段特性

令 x = 1<<n,即 x 为 2 的 n 次方,它具有以下性质假设x=16:

x   : 00010000
x-1 : 00001111
令一个数 y 与 x-1 做与运算,可以去除 y 位级表示的第 4 位以上数:

y       : 10110010
x-1     : 00001111
y&(x-1) : 00000010
这个性质和 y 对 x 取模效果是一样的:

y   : 10110010
x   : 00010000
y%x : 00000010


得出结论 y%x == y&(x-1)

位运算的代价比求模运算小的多,因此在进行这种计算时用位运算的话能带来更高的性能,

确定桶下标的最后一步是将 key 的 hash 值对桶个数取模:hash%capacity,如果能保证 capacity 为 2 的 n 次方,那么就可以将这个操作转换为位运算。

static int indexFor(int h, int length) {
    return h & (length-1);
}

HashMap初始大小那什么要为16呢,HashMap的扩容为什么要是2倍

2的N次方可以根据上诉性质采用位运算,所以为了提高性能初始大小为2的N次方,作为默认容量,太大和太小都不合适,所以16就作为一个比较合适的经验值被采用了

HashMap初始大小为2的N次方还有一个好处,再扩容时能大大减少计算的复杂度

对于一个key的hash值  

hash(key的hash值) & oldCapacity  = 1  桶位置为 桶位置和原来一致 + oldCapacity

hash(key的hash值) & oldCapacity  = 0 桶位置和原来一致

假设oldCapacity = 16  key1 = 18 key2 = 33
oldCapacity  : 00010000
newCapacity  : 00100000

key1 hashCode: 00010010
key1 hashCode: 00100001

key1 & oldCapacity = 1  数组下标为 2(原桶位置)+ oldCapacity = 18
key2 & oldCapacity = 0  数组下标为 1 (原桶位置)= 1

 加载因子什么是0.75?

提高空间利用率和 减少查询成本的折中,主要是泊松分布,0.75的话碰撞最小。

加载因子过高,例如为1,虽然减少了空间开销,提高了空间利用率,但同时也增加了查询时间成本;

加载因子过低,例如0.5,虽然可以减少查询时间成本,但是空间利用率很低,同时提高了rehash操作的次数。

在设置初始容量时应该考虑到映射中所需的条目数及其加载因子,以便最大限度地减少rehash操作次数,所以,一般在使用HashMap时建议根据预估值设置初始容量,减少扩容操作。

选择0.75作为默认的加载因子,完全是时间和空间成本上寻求的一种折衷选择

https://blog.csdn.net/diaopai5230/article/details/101211014

https://github.com/CyC2018/CS-Notes/blob/master/notes/Java%20%E5%AE%B9%E5%99%A8.md

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值