HashTable、HashMap、ConcurrentHashMap的区别
HashTable、HashMap、ConcurrentHashMap的区别在面试题常常会被问到,所以总结一下。既然要说区别,无非从下面几个方面比较(注意本文是基于jdk1.8):
1)底层数据结构??
2)什么初始化??怎么初始化??
3)线程安全??
4)key和value可不可以为null?
5)什么时候扩容,扩容机制??
-
底层数据结构
HashTable的底层数据是:数组+链表。
HashMap和ConcurrentHash的底层数据:数组+链表+红黑树。对于HashMap和ConcurrentHashMap有一个TREEIFY_THRESHOLD=8,当某个链表上的节点数达到这个值时,就会尝试将该链表转化为红黑树,具体要看table的大小,如果table.lenght()<MIN_TREEIFY_CAPACITY,则会进行扩容,MIN_TREEIFY_CAPACITY大小为64,否则就将链表转化为红黑树。
-
初始化
HashTable是在new HashTable的时候初始化table,默认的初始化大小为11,loadfactor是0.75,如果用户指定了初始化大小,则根据指定的大小初始化(如果指定的为0,则初始化大小为1)。
HashMap和ConcurrentHashMap的的初始在首次put的时候,如果首次put时,table为null,则会初始化,默认的初始化大小为16,loadfactor是0.75,如果用户指定的初始化大小为initialCapacity,那么table初始化容量为:首个大于等于initialCapacity + (initialCapacity >>> 1) + 1的2^n的数。 -
线程安全
HashTable和ConcurrentHashMap是线程安全的,HashMap是线程不安全的,
HashTable使用的是Sychronized,锁的是整个Table,锁颗粒度太大。
ConcurrentHashMap在jdk1.7将table分为若干个段,对每个段分别加锁。在jdk1.8 ConcurrentHashMap抛弃了段的概念,锁的是table上的一个Node,ConcurrentHashMap使用了CAS和Synchronized来确保线程安全。
HashMap线程不安全。 -
key和value可以不可以为null
HashTable的key和value都不能为null,会对valuenull判断,如果valuenull则会抛出NullPointerException异常,后面求hash=key.hashCode(),如果key==null则也会抛出NullPointerException异常。
ConcurrentHashMap的key和value都不能为null, if (key == null || value == null) throw new NullPointerException();
HashMap的key和value都可以为null,如果key=null,则hash=0. -
扩容机制
都是到达threshold进行扩容,不同的是HashTable的扩容是 1.5*old+1,而HashMap和ConcurrentHashMap则是2被扩容,保证容量是2的整次幂。
推荐阅读
-
Java中HashMap和TreeMap的区别深入理解
-
对比Hashtable,HashMap,TreeMap,谈谈对HashMap的理解
-
java中Hashtable和HashMap的区别分析
-
HashTable、HashSet和Dictionary的区别点总结
-
HashMap和Hashtable的详细区别
-
Java中HashMap和TreeMap的区别深入理解
-
Java自学-集合框架 HashMap和Hashtable的区别
-
对比Hashtable,HashMap,TreeMap,谈谈对HashMap的理解
-
HashTable与ConcurrentHashMap的区别
-
HashMap在jdk1.7和1.8中的区别