hashMap总结

目录

hashMap

1、haspmap扩容机制

2、hashmap为啥会有线程安全问题?

3、hashMap、hashTable、ConcurrentHashMap对比?

4、JDK1.7 和1.8 关于hashMap尾插

5、参考文章

 


hashMap

1、haspmap扩容机制

 

1、什么是扩容机制?

当数据容量超过当前最大容量*loadfactor(loadfactor表示扩容因子)时,容量自动扩大2倍,并将当前的数据重新放入新的hashmap中。所以初始的定义大小为2^n的大小最佳。

 

2、什么是resize?

resize就是重新计算容量;当我们不断的向HashMap对象里不停的添加元素时,HashMap对象内部的数组就会出现无法装载更多的元素,这是对象就需要扩大数组的长度,以便能装入更多的元素;当然Java里的数组是无法自动扩容的,方法的本质是使用一个新的数组代替已有的容量小的数组;就像我们用一个小桶装水,如果想装更多的水,就得换大水桶。

 

3、什么时候需要resize()?

当向容器添加元素的时候,会判断当前容器的元素个数,如果大于等于阈值—即当前数组的长度乘以加载因子的值的时候,就要自动扩容。


2、hashmap为啥会有线程安全问题?

本质原因:put()、addEntry()、resize()方法不是同步的,导致多线程并发的时候会出错,造成数据不一致、覆盖、死循环的错误。比如,JDK7中HashMap并发put会造成循环链表,导致get时出现死循环此问题在JDK8中已经解决。

 

1、put的时候导致的多线程数据不一致。

这个问题比较好想象,比如有两个线程A和B,首先A希望插入一个key-value对到HashMap中,首先计算记录所要落到的桶的索引坐标,然后获取到该桶里面的链表头结点,此时线程A的时间片用完了,而此时线程B被调度得以执行,和线程A一样执行,只不过线程B成功将记录插到了桶里面,假设线程A插入的记录计算出来的桶索引和线程B要插入的记录计算出来的桶索引是一样的,那么当线程B成功插入之后,线程A再次被调度运行时,它依然持有过期的链表头但是它对此一无所知,以至于它认为它应该这样做,如此一来就覆盖了线程B插入的记录,这样线程B插入的记录就凭空消失了,造成了数据不一致的行为。

2、HashMap的get操作在并发时,可能因为resize而引起死循环(cpu100%)

具体需要分析源码,参考资料 https://juejin.im/post/5ba457a25188255c7b168023


3、hashMap、hashTable、ConcurrentHashMap对比?

 主要特点线程是否安全原因
hashMapHashMap内部是保存链表头节点的桶数组,根据key的hashCode值来保存value,需要注意的是,HashMap不保证遍历的顺序和插入的顺序是一致的 
hashTable HashTable类是线程安全的,它使用synchronize来做线程安全,全局只有一把锁,在线程竞争比较激烈的情况下hashtable的效率是比较低下的
ConcurrentHashMap ConcurrentHashMap使用了分段锁技术来提高了并发度,不在同一段的数据互相不影响,多个线程对多个不同的段的操作是不会相互影响的。
hashMap 子类--LinkedHashMap与HashMap的区别在于LinkedHashMap保存了记录插入的顺序。  
TreeMapTreeMap实现了SortedMap接口,TreeMap有能力对插入的记录根据key排序,默认按照升序排序,也可以自定义比较强,在使用TreeMap的时候,key需实现Comparable  

4、JDK1.7 和1.8 关于hashMap尾插

HashMap在jdk1.7中采用头插入法,在扩容时会改变链表中元素原本的顺序,以至于在并发场景下导致链表成环的问题。而在jdk1.8中采用尾插入法,在扩容时会保持链表元素原本的顺序,就不会出现链表成环的问题了。

 区别
JDK1.7HashMap默认采用数组+单链表方式存储元素,当元素出现哈希冲突时,会存储到该位置的单链表中。
JDK1.8当单链表中元素个数超过8个时,会进而转化为红黑树存储,巧妙地将遍历元素时时间复杂度从O(n)降低到了O(logn))
JDK1.7 头插法扩容时改变链表中元素原本的顺序,以至于在并发场景下导致链表成环的问题。
JDK1.8 尾插法在扩容时会保持链表元素原本的顺序,就不会出现链表成环的问题了。(链表成环问题解决!

5、参考文章

1) https://blog.csdn.net/hefenglian/article/details/79763634?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值