java之HashMap

1. 存储结构

为提高查找效率,HashMap采用了数组+链表+红黑树的方式存储数据。主干是个数组,该数组的每个元素都是一个Node<K,V>。

2. 工作原理

新增一个元素时,会调用HashMap的put()方法。根据key计算hash值,根据hash值和数组长度得到数组下标。
不同的key有可能hash值相同,即该位置的数组中的元素出现两个,这就是哈希碰撞,为提高查找效率,hashmap采用链表形式进行存储。
相同的key,hash值也可能相同,则会遍历对应下标下的链表,新的Node覆盖旧的Node。
在jdk8中,当链表长度超过阈值(8)时,就会将链表转换为红黑树,这样大大减少了查找时间[查询时间从O(n)变为了O(logn)]。

3. 扩容

hashMap的主干是数组,当使用空间达到总空间的0.75时,就要对数组进行扩容。新建一个长度为之前数组2倍的新的数组,把原数组中的元素放入新数组中,同时把原数组中的引用置null,以便垃圾回收。

当重新调整HashMap大小的时候,多线程下存在条件竞争(race condition),因为如果两个线程都发现HashMap需要重新调整大小了,它们会同时试着调整大小。在调整大小的过程中,对应链表中元素的次序会反过来,因为移动到新数组的位置时,HashMap并不会将元素放在链表的尾部,而是放在头部,这是为了避免尾部遍历(tail traversing)。如果条件竞争发生了,那么就死循环了。

4. 重写equals方法需同时重写hashCode方法

put和get都首先会调用hashcode方法,去查找相关的key,当有冲突时,再调用equals方法。
若不重写hashcode方法,则存入该元素时的hash值和取出该元素的hash值不同,就会出现返回null的情况。

put和get操作相同,key-->hash-->index->最终索引位置 ,由于二者的hash值不同,导致没有定位到数组的同一个下标位置而返回逻辑上错误的值null。若碰巧定位到一个数组位置,也会判断其hash值是否相等,不相等,还是会返回null。  

5. 多线程下使用HashMap

线程安全上:HashTable > ConcurrentHashMap > HashMap(线程不安全)
HashTable是线程安全的,因为它的所有CRUD操作都被synchronized修饰,但在线程竞争激烈的情况下HashTable的效率非常低下。ConcurrentHashMap同步性能更好,因为它仅仅根据同步级别对map的一部分进行上锁,效率比HashTable高。故ConcurrentHashMap实现了更高级的线程安全,推荐。

6. 参考

面试必备:HashMap源码解析(JDK8)

HashMap底层存储原理

HashMap的实现原理和底层结构

HashMap常见问题

高并发下的HashMap有哪些问题?

面试必备:HashMap、Hashtable、ConcurrentHashMap的原理与区别

ConcurrentHashMap,hashtable以及两者比较

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值