【多线程】--HashMap、HashTable和ConcurrentHashMap的联系与区别

HashMap、HashTable和ConcurrentHashMap的联系与区别

HashMap基于哈希表的Map接口实现,是以key-value存储形式存在,即主要用来存放键值对。HashMap 的实现不是同步的,这意味着它不是线程安全的。

HashTable和ConcurrentHashMap都是对HashMap的优化,HashMap是线程不安全的集合类,HashTable和ConcurrentHashMap都是线程安全的,且ConcurrentHashMap又是进一步优化的。


🎯回顾Hashmap
  1. HashMap 的key、value都可以为null,键位置是唯一的。

  2. HashMap中的映射不是有序的。

  3. HashMap 的默认初始容量是16。

  4. JDK1.8 以后HashMap 使用的数据结构是:数组 + 链表 + 红黑树。 变为红黑树的目的是为了高效的查询

  5. JDK1.8 以后链表与红黑树之间的转换条件

    • 如果链表长度>8时,并且链表个数>64时,才会将链表转换为红黑树。如果链表个数不满足条件只会对数组进行扩容。

    • 如果链表长度 < 6时,红黑树又转化为链表。

HashTable和ConcurrentHashMap的键和值不能为null,因为在并发的环境下, 通过get(key)的时候,你不知道是因为key为null而返回的null还是之前put进去的值为null.

🔭HashMap结构图:

HashMap


HashTable与ConcurrentHashMap(JDK1.8 )区别

🎯1.加锁策略

HashTable是对通过在其所有公共方法上使用 synchronized 关键字来实现线程安全。这意味着在任何时候,只有一个线程可以访问 HashTable 的状态。

ConcurrentHashMap抛弃了原有的 jdk1.7版本的Segment 分段锁,而采用了 CAS + synchronized 来保证并发安全性。在 jdk1.8 中,ConcurrentHashMap 的内部结构改为了一个 Node 数组,每个 Node 是一个链表或红黑树(在链表长度超过一定阈值时转换为红黑树)。put方法,当数组中被Hash的位置为null,使用CAS新建Node对象,写入数组对应的位置,当数组中指定位置不为null时,通过synchronized,把Node节点添加入数组(链表<8)或者红黑树(链表>=8)。

HashTable

ConcurrentHashMap

虽然HashTable与ConcurrentHashMap都保证了线程安全,但是前者会造成多余的竞争锁,效率自然下降。

🔍注意:

HashTable的底层数据结构是: 数组 + 链表

ConcurrentHashMap(jdk1.8)的底层数据结构是: 数组 + 链表 + 红黑树


🎯2.扩容策略

HashTable:和HashMap的扩容方式相同,先申请一个更大的空间,然后将原来的数据直接拷贝过去,相当于获得一个新的对象。

ConcurrentHashMap:先申请一个更大的空间,但是不直接全部拷贝过去,只是拷贝一部分,每次对数组操作都会拷贝一部分


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值