HashMap 的几个要点

本文探讨了HashMap在JAVA中的实现,详细解释了其基于"链表散列"的数据结构,并重点介绍了initialCapacity和loadFactor这两个关键参数的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、HashMap的数据结构是”链表散列”,具体如下:


2、两个参数:initialCapacity 、loadFactor

其中initialCapacity 决定了上图所示的table的被初始创建的长度,当然这还不是初始长度,初始长度是大于initialCapacity 的最小的2的n次方,(为什么不能直接用initialCapacity作为初始长度呢?待会会分析到2的n次方的table长度的好处,一是可以优化取模的计算,如何优化待会分析。二是散列均匀,其实这就是取模的好处了)。
loadFactor*初始长度就是hashmap的扩容阈值,至于为什么要扩容,那是因为要避免上图的链表过长。
源代码如下:

3、链表存的是什么?

这里有个问题,就是为什么Entry为什么不只存有key值就好,还要多存key的hash值呢?
先看一下hashmap的put方法的源代码:

通过源码我们可以清晰看到HashMap保存数据的过程为:首先判断key是否为null,若为null,则直接调用putForNullKey方法。若不为空则先计算key的hash值,然后根据hash值搜索在table数组中的索引位置,如果table数组在该位置处有元素,则通过比较是否存在相同的key,若存在则覆盖原来key的value,否则将该元素保存在链头(最先保存的元素放在链尾)。若table在该处没有元素,则直接保存。

其实put时,会调用key的两个方法,一个是hashCode(),一个是equals(),两个对象相等的条件是hashCode和equal相等,或者是hashcode()和key1==key2,其中hash()是将key转化成一种新的表达,有key1!=key2 可以推出 hash(key1)!=hash(key2)。但是这对于数值型这个规律是满足现实看法的。但是对于对象不一样了,如我新建了两个学生对象,存了相同的学生信息,现实中这两个对象是对应同一个学生的,所以这两个对象应该是相等的,但是由于对象的地址空间不同,所以hashCode(key1)!=hashCode(key2),而且对象的key1.equal(key2)默认是key1==key2,所以程序判断这两个程序判断这两个对象是不相等的,这是有悖于实际的。
结论:hashcode()得到的一个数值,这是是对象的唯一的号,所以当hashcode相同的时,equals()得到的结果也应该相同,(因为hashcode相同说明两个对象在现实生活中是等价的,所以它们比较的结果也应该是相同),所以我们对equals方法进行了重写,建议一定要对hashCode方法重写,以保证相同的对象返回相同的hash值,不同的对象返回不同的hash值。避免hashcode相同,而equals不同。

4、上图的表长为什么要是2的n次方?
为了避免key的hash值超过表的长度,所以必须对key的hash值做以下处理:hash(key)%length,其中length为表的长度,但是取模是很耗时的,所以能不能通过位的与操作来代替取模的操作呢?答案是:当length=2的n次时,hash(key)%length等价于 hash(key) &(length-1)
而取模的源代码如下:


参考链接:
http://mp.weixin.qq.com/s?__biz=MjM5MTM0NjQ2MQ==&mid=2650140213&idx=2&sn=3a921452cc4616caa12e70665c0f599d&chksm=beb7b44789c03d51f47624c493630059a4011a3f67aa9b6634decdcf5f403c565093187a067e&mpshare=1&scene=1&srcid=0225QS1R6PNzn7koY1cC6F0b#rd







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值