【Java EE】HashMap、HashTable、ConcurrentHashMap的区别

本文介绍了HashMap的基本概念,包括其非线程安全特性,哈希冲突的处理方式。重点比较了HashMap与线程安全的HashTable和ConcurrentHashMap在线程同步、性能及实现方式上的差异。

一、HashMap

   ·HashMap是基于哈希表的Map接口实现的,以key-value的存储形式存在。由于HashMap的实现不是同步的,这意味着它不是线程安全的。他的key,value都可以为null,除此之外HashMap中的映射不是有序的。

  ·在jdk1.8之前HashMap由数组+链表组成,数组的HashMap的主体,链表主要是为了解决哈希冲突(两个对象调用的hashCode方法计算的哈希值,经哈希函数算出来的地址被别的元素占用)。jdk1.8之后解决哈希冲突有了较大的变化,当链表长度大于阈值或者红黑树的边界值(默认为8),并且当前数组的长度大于64时,此时此索引位置上的所有数据改为使用红黑树存储。

二、HashMap与HashTable的区别

 HashMap和HashTable都实现了Map接口,但是决定用哪一个之前先弄清他们之间的区别,主要区别有:线程安全,同步以及速度。

1.HashMap和HashTable几乎可以等价,但是HashMap是不能同步(synchronized)的并且可以接受key和value是null值的。HashTable不行。

2.由于HashTable是synchronized的,这意味着HashTable是线程安全的,多个线程可以共享一个HashTable

3.由于HashTable是线程安全的,所以在单线程环境下比HashMap慢

4.HashMap不能保证随着时间的推移Map中的元素次序是不变的

三、CorrentHashMap

  CorrentHashMap可以说是HashMap的升级版,CorrentHashMap是线程安全的,但是与HashTable实现线程安全的方式不同。

  HashTable是通过对hash表结构进行锁定,是阻塞式的,当一个线程占有这个锁时,其他线程必须阻塞等待其释放锁。CorrentHashMap是采用分离锁的方式,它并没有对整个哈希表进行锁定,而是局部锁定,也就是说当一个线程占有这个局部锁时,不影响其他线程对哈希表的其他地方访问。

   CorrentHashMap对读操作没有加锁(但是使用了 volatile 保证从内存读取结果), 只对写操作进行加锁.

   加锁的方式仍然 是是用 synchronized, 但是不是锁整个对象, 而是 "锁桶" (用每个链表的头结点作为锁对象), 大大降 低了锁冲突的概率.

   充分利用 CAS 特性. 比如 size 属性通过 CAS 来更新. 避免出现重量级锁的情况.

  优化了扩容方式: 化整为零 发现需要扩容的线程, 只需要创建一个新的数组, 同时只搬几个元素过去. 扩容期间, 新老数组同时存在. 后续每个来操作 ConcurrentHashMap 的线程, 都会参与搬家的过程. 每个操作负责搬运一小 部分元素. 搬完最后一个元素再把老数组删掉. 这个期间, 插入只往新数组加. 这个期间, 查找需要同时查新数组和老数组

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小劉要努力~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值