HashMap和HashTable以及ConcurrentHashMap的区别

如标题所示,这个是在java面试中被问频率最高的问题之一,经过我对于网上各种资料的收集和整理,这里会详细说明下二者的区别以及应用场景。

相同点

  • 都可以用来存储键值对
  • 底层哈希表结构查询速度都很快
  • 内部通过单链表解决冲突问题,容量不足会自动增加
  • 都实现了Map接口
  • 都实现了 Serializable 接口,支持序列化
  • 实现了 Cloneable 接口,可以被克隆

不同点

  • HashMap线程不安全,效率较高,HashTable是线程安全,效率较低。
  • HashMap的键和值都可以是null,HashTable的键和值都不可以是null,会抛出空指针异常
  • HashMap继承 AbstractMap 类,HashTable继承Dictionary类
  • HashMap使用Iterator遍历,HashTable使用Enumeration遍历
  • HashMap和HashTable的初始化方式和扩容方式不同,HashMap的初始大小为16,之后每次扩充容量为原来的两倍,HashTable的初始大小为11,之后每次扩充2n+1

实践测试

键值对是否可以为空测试

可以看到HashTable报错,是因为键值使用了null,单纯的使用key为null或者value为null都是会报错的,所以这个区别是很明显的

public class HashTest {
    public static void main(String[] args) {
        Map<String,String> hashMap=new HashMap<>();
        hashMap.put(null,"a");
        Map<String,String> hashTable=new Hashtable<>();
        hashTable.put(null,null);
    }
}
//执行结果
Exception in thread "main" java.lang.NullPointerException
	at java.util.Hashtable.put(Hashtable.java:460)
	at HashTest.main(HashTest.java:15)

Process finished with exit code 1

线程安全观察

在hashMap中是没有的

    public V get(Object key) {
        Node<K,V> e;
        return (e = getNode(hash(key), key)) == null ? null : e.value;
    }

在hashTable的源码发现了方法级同步锁

    @SuppressWarnings("unchecked")
    public synchronized V get(Object key) {
        Entry<?,?> tab[] = table;
        int hash = key.hashCode();
        int index = (hash & 0x7FFFFFFF) % tab.length;
        for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
            if ((e.hash == hash) && e.key.equals(key)) {
                return (V)e.value;
            }
        }
        return null;
    }

对于其他的关于继承啥的都可以在源代码中看到

ConcurrentHashMap是干嘛的

虽然jdk提供了HashMap和HashTable但是如何同时满足线程安全和效率高呢,显然这两个都无法满足,所以就诞生了ConcurrentHashMap神器,让我们应用于高并发场景。

该神器采用了分段锁策略,通过把整个Map分成N个Segment(类似HashTable),可以提供相同的线程安全,效率提升N倍,默认提升16倍。

ConcurrentHashMap的优点就是HashMap和HashTable的缺点,当然该神器也是不支持键值为null的

ConcurrentHashMap的出现也意味着HashTable的落幕,所以在以后的项目中,尽量少用HashTable。

应用场景

对于普通场景可以使用hashMap实现,如果是高并发场景建议使用ConcurrentHashMap实现

发表评论