hashMap和hashTable的区别
效率问题区分(线程安不安全)
* 1.HashMap是线程不安全的,效率高
* Hashtable是线程安全的,效率低
* 2.HashMap可以存储null键和null值
* Hashtable不可以存储null键和null值
继承的父类不同
HashTable继承Dictionary类,而hashMap继承了AbstractMap类,但是二者都实现了map接口。
线程安全性不同
Hashtable 线程安全,因为它每个方法中都加入了Synchronize。HashMap是线程不安全的。
Hashtable和HashMap的初始大小和扩容的方式。
HashTable中hash数组默认大小是11,增加的方式是 old*2+1。
HashMap中hash数组默认大小是16,增加的方式是 old*2。
是否提供contains方法
HashMap把Hashtable的contains方法去掉了,改成containsValue和containsKey,
因为contains方法容易让人引起误解。
Hashtable则保留了contains,containsValue和containsKey三个方法,
其中contains和containsValue功能相同。
解决hash冲突方式不同(地址冲突)
HashMap中,当出现冲突时可以:
1.如果冲突数量小于8,则是以链表方式解决冲突。
2.而当冲突大于等于8时,就会将冲突的Entry转换为**红黑树进行存储。**
3.而又当数量小于6时,则又转化为链表存储。
而在HashTable中, 都是以链表方式存储。
ConcurrentHashMap
底层采用分段的数组+链表实现,线程安全
• 通过把整个Map分为N个Segment,可以提供相同的线程安全,但是效率提升N倍,默认提升16倍。(读操作不加锁,由于HashEntry的value变量是 volatile的,也能保证读取到最新的值。)
• Hashtable的synchronized是针对整张Hash表的,即每次锁住整张表让线程独占,ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁分离技术
• 有些方法需要跨段,比如size()和containsValue(),它们可能需要锁定整个表而而不仅仅是某个段,这需要按顺序锁定所有段,操作完毕后,又按顺序释放所有段的锁
• 扩容:段内扩容(段内元素超过该段对应Entry数组长度的75%触发扩容,不会对整个Map进行扩容),插入前检测需不需要扩容,有效避免无效扩容
ConcurrentHashMap是使用了锁分段技术来保证线程安全的。
锁分段技术:首先将数据分成一段一段的存储,然后给每一段数据配一把锁,
当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。
ConcurrentHashMap提供了与Hashtable和SynchronizedMap不同的锁机制。Hashtable中采用的锁机制是一次锁住整个hash表,从而在同一时刻只能由一个线程对其进行操作;而ConcurrentHashMap中则是一次锁住一个桶。
ConcurrentHashMap默认将hash表分为16个桶,诸如get、put、remove等常用操作只锁住当前需要用到的桶。这样,原来只能一个线程进入,现在却能同时有16个写线程执行,并发性能的提升是显而易见的。