HashMap源代码阅读小结

这里将个人阅读源代码后获得的信息以文字不带代码的方式写出来,个人认为有助于自己在面试时候更清晰表达自己想说的东西。

HashMap底层实现原理:以数组为主干,链表为分支的方式存储数据。数组中的所有key-value的key的hash值都不相同;链表中,所有key-value的key的hash值相同。

具体添加数据(put方法)时,如果根据key计算出的hash值对应的位置没有数据,则将需要添加的数据放在hash值对应的位置上,如果对应的位置已存在数据,则将新数据的next引用指向数组中的key-value数据,然后将新数据放到数组中hash值对应的位置上。当然hash值的算法已经做了足够的优化来尽量避免不同的key进行hash计算产生相同的hash值,并且尽量使数组中的位置能够得到充分的使用,以提高数据获取时的查询效率。

获得数据时(get方法)首先根据key的hash值,找到数组中对应的位置,然后通过比较key是否相同,找到对应的value。

对于HashMap使用的一些注意点:构造方法有3个:无任何参数;带一个初始容量;带初始容量和负载因子;

初始容量简单的说是HashMap中数组最开始没有扩容前的长度,还有一个size是指存储在hashMap中的key-value对数,极限容量为当前容量与负载因子乘积的整数部分。当size值超过极限容量时,HashMap需要扩容。

初始容量的计算:调用构造方法时,如果未指定初始容量,则使用默认初始容量为16,源码中以 1<<4 表示,如果指定了初始容量参数,如果参数值为2的n次方值,则该值即为HashMap初始容量,否则为大于该值的最小2的n次方值,如参数值为6,则初始容量为8,参数值为14时,初始容量为16。注意:该值并非在调用构造方法进行实例化的时候确定的,是在初次调用put方法时确定的。也就是说HashMap数组的长度最开始是在初次调用put方法时才确定的,存储空间也是初次调用put方法时申请的。

在这个过程中,hashMap的极限容量可能发生变化,按照一般的理解,在调用构造方法时指定初始容量,表明后续的操作过程中,将在该hashMap中存入初始容量个key-value,在构造函数中确实是如此处理的,初始容量的参数值被赋值给极限容量,但是在put方法中进行初始容量再计算时,极限容量重新计算为初始容量与负载因子的乘积,也就是说假如调用构造函数时传入的初始容量为7,负载因子为0.75,在未调用put方法前,hashMap的极限容量都是7,但是当存入第一个key-value后,hashmap的初始容量确定为8,此时极限容量重新计算为6,那么按照道理来说,在指定了初始容量之后,并没有完全的杜绝扩容问题,不知道大家有没有发现过这个问题,还是我有哪些地方理解偏差了。

扩容:当size 大于等于极限容量时,hashmap会扩容为当前容量(数组长度)的两倍。扩容后,需重新计算各个key-value在数组中的位置。所以hashmap扩容操作是相当消耗性能的。

hashMap不是线程安全的,如果在使用迭代器的过程中有其他线程修改了map,将抛出ConcurrentModificationException,这就是所谓fail-fast策略,而其他线程通过其他方式进行操作是无法识别的。

 

以上为小结全部内容,看到有误或不足之处请大家不吝指正,在此非常感谢!

 

转载于:https://my.oschina.net/u/183350/blog/748146

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值