HashMap、HashTable、ConcurrentHashMap区别

Java框架

浏览数:301

2019-1-23

疑问

在Java集合框架中,其中有一个大类就是map,其中HashMap算是最常用的map实现之一,而大家讨论HashMap的时候通常会和HashTableConcurrentHashMap一起比较,那么它们名字都带有hash字眼,而在实现与实际应用中有什么区别和注意事项,下面我们来讨论(这里都是基于JDK7的实现下进行讨论的)。

简介

HashMap

基于哈希表的 Map 接口的实现,此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。

除了非同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。

HashTable

此类实现一个哈希表,该哈希表将键映射到相应的值。任何非null 对象都可以用作键或值。

为了成功地在哈希表中存储和获取对象,用作键的对象必须实现 hashCode 方法和 equals 方法。

ConcurrentHashMap

支持get的完全并发和put的所期望可调整并发的哈希表。此类遵守与Hashtable相同的功能规范,并且包括对应于 Hashtable的每个版本的方法。

不过,尽管所有操作都是线程安全的,但不意味着get操作会锁定,并且不支持锁定整个表以某种防止所有访问的方式。此类可以通过程序完全与Hashtable进行互操作,这取决于其线程安全,而与其同步细节无关。

区别

主要区别

集合 key允许为null value允许为null 线程安全 同步机制
HashMap
HashTable synchronized
ConcurrentHashMap lock,java8之后改为synchronized

HashMap与HashTable

HashMap与HashTable在使用和实现上基本没有什么却别,其中主要却别是:

  • HashMap非线程安全,HashTable是线程安全的
  • HashTable为了保证线程安全使用synchronized实现,必然也影响性能
  • HashTable不允许null作为key和value,而HashMap允许
  • HashMap默认初始化大小为16,HashTable为11;HashMap扩容时是扩大两倍,而HashTable扩容是两倍加一

还有一点就是,HashTable继承自java.util.Dictionary类,有相关字典类的操作,例如keyselements等接口。

HashTable与ConcurrentHashMap

HashTable虽然是线程安全,但是是通过synchronized机制做了简单的实现,无论搜索操作的时候都是对整理哈希表锁定,比较影响性能。

ConcurrentHashMap的提出就是为了解决这个问题。不同于HashTable,ConcurrentHashMap是通过Segment进行分隔从而只是锁住哈希表的一部分,提高性能,这也是两者的主要区别。

HashMap和ConcurrentHashMap

对于HashMap和ConcurrentHashMap在API上基本没什么却别,只不过在实现和使用上有点区别:

  • 数据结构不同,ConcurrentHashMap在HashMap基础通过Segment进行分隔
  • 线程安全,HashMap非线程安全,而ConcurrentHashMap是线程安全的,但不代表多线程访问的时候对于通用的key拿到同样的值

总结

从上面可以看出,对于从Java1.0版本就提出来的HashTable其实已经过时(并不是deprecated,只是使用上过时),因为对于普通的Map使用场景使用HashMap就足够了,而对于多线程并发的场景下ConcurrentHashMap表现出更好的性能,所以日常的使用HashMap和ConcurrentHashMap就足够了,而HashTable的存在可能就是Java平台保持兼容性而一直留下来的吧。

原文地址:https://www.jianshu.com/p/0e3c7bfa6064