HashMap的默认长度为什么是16?

如果两个元素不相同,但是hash函数的值相同,这两个元素就是一个碰撞

因为把任意长度的字符串变成固定长度的字符串,所以存在一个hash对应多个字符串的情况,所以碰撞必然存在

为了减少hash值的碰撞,需要实现一个尽量均匀分布的hash函数,在HashMap中通过利用key的hashcode值,来进行位运算
公式:index = e.hash & (newCap - 1)

举个例子:
1.计算"book"的hashcode
    十进制 : 3029737
    二进制 : 101110001110101110 1001

2.HashMap长度是默认的16,length - 1的结果
    十进制 : 15
    二进制 : 1111

3.把以上两个结果做与运算
    101110001110101110 1001 & 1111 = 1001
    1001的十进制 : 9,所以 index=9

hash算法最终得到的index结果,取决于hashcode值的最后几位

为了推断HashMap的默认长度为什么是16
现在,我们假设HashMap的长度是10,重复刚才的运算步骤:
hashcode : 101110001110101110 1001
length - 1 :                                     1001
index :                                            1001

再换一个hashcode 101110001110101110 1111 试试:
hashcode : 101110001110101110 1111
length - 1 :                                     1001
index :                                            1001

从结果可以看出,虽然hashcode变化了,但是运算的结果都是1001,也就是说,当HashMap长度为10的时候,有些index结果的出现几率
会更大
而有些index结果永远不会出现(比如0111),这样就不符合hash均匀分布的原则

反观长度16或者其他2的幂,length - 1的值是所有二进制位全为1,这种情况下,index的结果等同于hashcode后几位的值
只要输入的hashcode本身分布均匀,hash算法的结果就是均匀的


所以,HashMap的默认长度为16,是为了降低hash碰撞的几率

参考了https://blog.youkuaiyun.com/zjcjava/article/details/78495416

<think>好的,我现在要回答用户关于HashMap默认负载因子为什么是0.75的问题。首先,我需要回忆一下HashMap的基本原理,负载因子的作用,以及为什么选择这个数值。 首先,负载因子是HashMap在扩容之前允许的填充程度。当元素数量超过容量乘以负载因子时,就会触发扩容。比如默认容量16,负载因子0.75时,当元素超过12个就会扩容到32,依此类推。 接下来,用户想知道为什么选择0.75这个特定值。这可能涉及到时间和空间成本的权衡。负载因子高意味着更少的扩容操作,节省空间,但可能导致哈希冲突增加,查找时间变长。负载因子低则相反,空间占用多,但查找效率高。 我记得Java官方文档中有提到,0.75是在时间和空间成本之间的一种折中选择。可能还有数学上的依据,比如泊松分布或者概率论中的最优值。比如,在理想情况下,哈希冲突的概率较低时,0.75可能是一个平衡点,使得链表长度在大部分情况下保持较短,同时减少频繁的扩容。 另外,可能需要考虑哈希表的性能。比如,当负载因子为0.75时,哈希表的平均探测次数在开放地址法中可能达到一个较好的平衡。但Java的HashMap使用的是链表和红黑树(当链表过长时),所以可能这个数值经过测试验证,在大多数场景下性能最优。 此外,可能需要解释负载因子与哈希冲突的关系。较高的负载因子导致更多冲突,而较低的则减少冲突。但扩容是有成本的,所以需要找到一个合适的阈值。 可能需要引用一些资料或官方说明。例如,在Java的HashMap文档中提到,默认负载因子0.75提供了时间和空间效率的良好平衡。较高的值减少了空间开销,但增加了查找成本。而0.75是两者之间的妥协。 总结起来,答案应该包括负载因子的定义,为什么0.75被选中的原因(时间和空间的平衡,数学或经验依据),可能还提到哈希冲突的影响以及扩容的开销。</think><< HashMap的负载因子默认设置为0.75是时间和空间成本之间的折中结果。负载因子(Load Factor)表示哈希表在扩容前允许的填充程度,计算公式为:`元素数量 / 容量`。当元素数量超过`容量 × 负载因子`时,哈希表会触发扩容(容量翻倍,重新哈希)。以下是具体原因: 1. **空间效率与时间效率的平衡** - 负载因子过高(如1.0):虽然减少了内存占用,但会导致哈希冲突概率显著增加,链表或红黑树的查询时间复杂度可能退化到O(n)或O(log n)。 - 负载因子过低(如0.5):虽然减少了哈希冲突,提高了查询效率,但会导致频繁扩容,增加时间和内存的开销。 2. **统计学和数学依据** - 在理想哈希函数下,0.75的负载因子对应的哈希冲突概率较低。根据泊松分布,当负载因子为0.75时,哈希表中每个桶(Bucket)的链表长度超过8的概率极小(约千万分之一),适合实际应用场景。 3. **经验验证** - 实际测试表明,0.75在大多数场景下能平衡扩容频率和哈希冲突。例如,默认容量16时,扩容阈值是12(16 × 0.75),在插入第13个元素时触发扩容。 **示例代码**:默认负载因子在HashMap构造函数中的体现 ```java HashMap<String, Integer> map = new HashMap<>(); // 默认负载因子0.75 HashMap<String, Integer> customLoadMap = new HashMap<>(16, 0.5f); // 自定义负载因子0.5 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值