蚂蚁花呗:阿里巴巴面试:Java 集合知识点(附图文解析)( 六 )
- 创建时如果给定了容量初始值 , 那么 Hashtable 会直接使用你给定的大小 , 而 HashMap 会将其扩充为2的幂次方大小 。 也就是说 HashMap 总是使用2的幂次方作为哈希表的大小后面会介绍到为什么是2的幂次方 。
- 底层数据结构: JDK1.8 以后的 HashMap 在解决哈希冲突时有了较大的变化 , 当链表长度大于阈值(默认为8)时 , 将链表转化为红黑树 , 以减少搜索时间 。 Hashtable 没有这样的机制 。
- HashMap的迭代器(Iterator)是fail-fast迭代器 , 但是 Hashtable的迭代器(enumerator)不是 fail-fast的 。 如果有其它线程对HashMap进行的添加/删除元素 , 将会抛出ConcurrentModificationException , 但迭代器本身的remove方法移除元素则不会抛出异常 。 这条同样也是 Enumeration 和 Iterator 的区别 。
Hashtable , 是线程安全的 , 它在所有涉及到多线程操作的都加上了synchronized关键字来锁住整个table , 这就意味着所有的线程都在竞争一把锁 , 在多线程的环境下 , 它是安全的 , 但是无疑是效率低下的 。
JDK1.7 实现Hashtable 容器在竞争激烈的并发环境下表现出效率低下的原因 , 是因为所有访问 Hashtable 的线程都必须竞争同一把锁 , 那假如容器里有多把锁 , 每一把锁用于锁容器其中一部分数据 , 那么当多线程访问容器里不同数据段的数据时 , 线程间就不会存在锁竞争 ,, 这就是ConcurrentHashMap所使用的锁分段技术 。
在 JDK1.7版本中 , ConcurrentHashMap 的数据结构是由一个 Segment 数组和多个 HashEntry 组成 。 Segment 数组的意义就是将一个大的 table 分割成多个小的 table 来进行加锁 。 每一个 Segment 元素存储的是 HashEntry数组+链表 , 这个和 HashMap 的数据存储结构一样 。
ConcurrentHashMap 类中包含两个静态内部类 HashEntry 和 Segment 。 HashEntry 用来封装映射表的键值对 , Segment 用来充当锁的角色 , 每个 Segment 对象守护整个散列映射表的若干个桶 。 每个桶是由若干个 HashEntry 对象链接起来的链表 。 一个 ConcurrentHashMap 实例中包含由若干个 Segment 对象组成的数组 。 每个 Segment 守护着一个 HashEntry 数组里的元素 , 当对 HashEntry 数组的数据进行修改时 , 必须首先获得它对应的 Segment 锁 。
推荐阅读
- 阿里巴巴|反击开始!马云、马化腾、任正非相继出手,网友炸锅:干得漂亮
- 阿里巴巴|电商风云再起?拼多多来势汹汹,疯狂攻击阿里“命门”!
- 数码科技大爆炸|支付宝再次上线新功能!月光族有福气了:花呗支付可免首付无利息
- 阿里巴巴|好戏还在后面!英国尝到“苦头”,美国表态:不关我的事
- 蚂蚁花呗|支付宝再次上线新功能! \月光族\有福气了: 花呗支付可免首付无利息
- 蚂蚁花呗|你可能一直在错误的使用支付宝和蚂蚁花呗
- 产业气象站|会对车贷、房贷产生影响?花呗客服回应,花呗部分用户接入央行征信
- 阿里巴巴|你觉得华为与阿里巴巴,谁掌握的世界性先进技术比更多?
- 蚂蚁花呗|支付宝花呗“服务升级”,这些行为将上报征信!
- 阿里巴巴|马云不再沉默,面对印度的施压,阿里直接遣散印度公司员工
