一、JAVA集合类、深入理解HashMap

HashMap作为我们最常用的一个类,而且在面试题中频频出现,让我们来一探究竟吧。

HashMap类图:实现了Map、Cloneable和Serializable类,继承了AbstractMap类。


HashTable维护了一个Entry的数组,初始值为长度为0的空数组,如下:

 

先看一段简单的代码:

构建函数如下:

默认值定义如下:

由上面的构造函数可知,初始化对象主要设置了HashMap的两个属性:

loadFactor: 加载因子,当HashMap中的个数达到这个比例时,HashMap扩容一倍。

threshold: 是HashMap的阈值,用于判断是否需要调整HashMap的容量。threshold的值="容量*加载因子",当HashMap中存储数据的数量达到threshold时,就需要将HashMap的容量加倍。

构造方法中设定了初始容量必须是2的倍数 (while循环)

 
HashMap的put方法:

在put方法中,先判断了table是否为空,如果为空,则初始化一个threshold大小的数组;

如果key为null,则放入table数组的第0个元素中;

否则,根据key的hash码找到对应数组中的索引,并判断该位置是否有相同key的元素,如果key相同,则替换value值,不同的话,modCount++,并调用addEntry新增了一个元素。


addEntry中判断了table的元素数量是否超过了threshold值,超过了将重新将table扩容两倍,并将之前的table元素映射到新的table中,再插入新的元素。


由上图可知,插入新元素时,如果当前索引上有entity(之前已经判断了key的hash值相同且key相同时会覆盖value,这里出现了两个不同的key有相同的hash值得情况),则新元素的next指向了旧的entity,即如下图



下面我们再来看看HashMap的get方法:


主要是调用了一个getEntry方法,如下:


方法中可以看到,getEntry根据key的hash值得到了它在table中的索引,并且循环调用了e.next获取到匹配到key的元素(即关键还是key.equals(k)判断,hash值只是定位到它在table中的索引)。

Entity是一个单向列表结构,这样在key的hash值冲突(不同的key的hash值算出了相同的index)时,采用链表式的存储,由于这种实现方式,无论key中存储了何种类型的值,只要实现了相应的equals方法,都可以通过hash值快速得到其在table中的位置。这也是HashMap效率较高的原因。


经过上面的分析,也可以初步理解了为什么HashMap不能支持多线程,以下是我个人的一些想法,具体的原因后续再去探讨

原因1:HashMap会动态分配大小,多线程的情况下可能会出现两个线程同时重新分配大小的问题

原因2:由于HashMap的key值采用hash函数得到其相应的索引,并构造成为单向链表,如果多线程的情况下,可能会出现值覆盖的问题。

还有等等其它问题


学习整理阶段,希望对大家有用,有误之处,希望评论里指出哦








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值