欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

HashTable、HashMap、ConcurrentHashMap的区别

程序员文章站 2022-03-03 08:24:23
...
HashTable、HashMap、ConcurrentHashMap的区别在面试题常常会被问到,所以总结一下。既然要说区别,无非从下面几个方面比较(注意本文是基于jdk1.8):
1)底层数据结构??
2)什么初始化??怎么初始化??
3)线程安全??
4)key和value可不可以为null?
5)什么时候扩容,扩容机制??
  1. 底层数据结构
    HashTable的底层数据是:数组+链表。
    HashMap和ConcurrentHash的底层数据:数组+链表+红黑树。

    对于HashMap和ConcurrentHashMap有一个TREEIFY_THRESHOLD=8,当某个链表上的节点数达到这个值时,就会尝试将该链表转化为红黑树,具体要看table的大小,如果table.lenght()<MIN_TREEIFY_CAPACITY,则会进行扩容,MIN_TREEIFY_CAPACITY大小为64,否则就将链表转化为红黑树。

  2. 初始化
    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的数。

  3. 线程安全
    HashTable和ConcurrentHashMap是线程安全的,HashMap是线程不安全的,
    HashTable使用的是Sychronized,锁的是整个Table,锁颗粒度太大。
    ConcurrentHashMap在jdk1.7将table分为若干个段,对每个段分别加锁。在jdk1.8 ConcurrentHashMap抛弃了段的概念,锁的是table上的一个Node,ConcurrentHashMap使用了CAS和Synchronized来确保线程安全。
    HashMap线程不安全。

  4. 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.

  5. 扩容机制
    都是到达threshold进行扩容,不同的是HashTable的扩容是 1.5*old+1,而HashMap和ConcurrentHashMap则是2被扩容,保证容量是2的整次幂。