天道不一定酬所有勤
但是,天道只酬勤

我说我了解集合类,面试官竟然问我为啥HashMap的负载因子不设置成1!?

可能是2020年最全的超硬核Java 面试 “备战” 资料!(超过500页)

在Java基础中,集合类是很关键的一块知识点,也是日常开发的时候经常会用到的。比如List、Map这些在代码中也是很常见的。

个人认为,关于HashMap的实现,JDK的工程师其实是做了很多优化的,要说所有的JDK源码中,哪个类埋的彩蛋最多,那我想HashMap至少可以排前五。

也正是因为如此,很多细节都容易被忽视,今天我们就来关注其中一个问题,那就是:

为什么HashMap的负载因子设置成0.75,而不是1也不是0.5?这背后到底有什么考虑?

大家千万不要小看这个问题,因为负载因子是HashMap中很重要的一个概念,也是高端面试的一个常考点。

另外,这个值得设置,有些人会用错的,比如前几天我的《阿里巴巴Java开发手册建议创建HashMap时设置初始化容量,但是多少合适呢?》这篇文章中,就有读者这样回复:

-w356

-w375

既然有人会尝试着去修改负载因子,那么到底改成1是不是合适呢?为什么HashMap不使用1作为负载因子的默认值呢?

什么是loadFactory

首先我们来介绍下什么是负载因子(loadFactory),如果读者对这部分已经有了解,那么可以直接跨过这一段。

我们知道,第一次创建HashMap的时候,就会指定其容量(如果未显示制定,默认是16,详见为啥HashMap的默认容量是16?),那随着我们不断的向HashMap中put元素的时候,就有可能会超过其容量,那么就需要有一个扩容机制。

所谓扩容,就是扩大HashMap的容量:

void addEntry(int hash, K key, V value, int bucketIndex) {  
    if ((size >= threshold) && (null != table[bucketIndex])) {  
        resize(2 * table.length);  
        hash = (null != key) ? hash(key) : 0;
        bucketIndex = indexFor(hash, table.length);        }  
    createEntry(hash, key, value, bucketIndex);  
}  

从代码中我们可以看到,在向HashMap中添加元素过程中,如果 元素个数(size)超过临界值(threshold) 的时候,就会进行自动扩容(resize),并且,在扩容之后,还需要对HashMap中原有元素进行rehash,即将原来通中的元素重新分配到新的桶中。

在HashMap中,临界值(threshold) = 负载因子(loadFactor) * 容量(capacity)。

loadFactor是装载因子,表示HashMap满的程度,默认值为0.75f,也就是说默认情况下,当HashMap中元素个数达到了容量的3/4的时候就会进行自动扩容。(相见HashMap中傻傻分不清楚的那些概念

为什么要扩容

Hollis为了防爬虫以及未经授权的恶意转载,此处内容已被作者隐藏,请输入验证码查看内容
验证码:
请关注本站微信公众号,回复“验证码”,获取验证码。在微信里搜索“Hollis”或者“hollischuang”或者微信扫描右侧二维码都可以关注本站微信公众号。

(全文完) 欢迎关注『Java之道』微信公众号
赞(3)
如未加特殊说明,此网站文章均为原创,转载必须注明出处。HollisChuang's Blog » 我说我了解集合类,面试官竟然问我为啥HashMap的负载因子不设置成1!?
分享到: 更多 (0)

评论 2

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
  1. #1

    有一点不太理解,HashMap的容量(capacity)指的是数组的大小,即可存放key的个数。扩容应该是与哈希碰撞无关才对,极端情况下,即使容量扩增的很大,然而所有元素全部发生了哈希碰撞,结果仍然是退化成了一个链表吧?求解惑~

    xu6个月前 (03-19)回复
  2. #2

    楼主,看了你的文章很有收获。上面的loadFactory拼写错误,没有字母y!

    tristate6个月前 (03-31)回复

HollisChuang's Blog

联系我关于我