面试题之HashMap与HashTable的区别
HashMap 与 HashTable 的区别
-
首先可以从源码中看出第一个区别:
继承的类不同
//HashMap public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable {...} //HashTable public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, java.io.Serializable {...}
- HashMap 继承了 AbstractMap 抽象类,并且实现了 Map 接口、Cloneable 接口、Serializable 接口。
- HashTable 继承了 Dictionary 抽象类,并且实现了 Map 接口、Cloneable 接口、Serializable 接口。
-
通过两者源码的无参构造函数可以看出:
两者默认容量不同
//HashMap // Constructs an empty HashMap with the default initial capacity (16) and the default load factor (0.75). public HashMap() { this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted } //HashTable // Constructs a new, empty hashtable with a default initial capacity (11) and load factor (0.75). public Hashtable() { this(11, 0.75f); }
- HashMap 的默认初始容量为16,填充因子为0.75。
- HashTable 的默认出事容量为11,填充因子为0.75。
-
是否支持null值作为key和value
- HashTable 不允许 null 值作为 key 和 value。
- HashMap 可以使用 null 值作为 key 和 value(由于 Map 是不可重复的集合,所有最多只允许一个 null 值作为 key)。
- 虽说 HashMap 支持 null 值作为 key,不过建议还是尽量避免这样使用,因为一旦不小心使用了,若因此引发一些问题,排查起来很是费事。HashMap 以 null 作为 key 时,总是存储在 table 数组的第一个节点上。
-
扩容方面的差别
-
HashMap 的元素个数超过阈值(容量 * 填充因子),则进行扩容
-
扩容结果:
新容量 = 旧容量 * 2
新阈值 = 新容量 * 填充因子
-
-
HashTable 的元素个数超过阈值(容量 * 填充因子),则进行扩容
-
扩容结果:
新容量 = 旧容量 * 2 + 1
新阈值 = 新容量 * 填充因子
-
-
-
HashMap与HashTable最主要的区别就是
线程安全问题
HashMap 是线程不安全的,HashTable 是线程安全的
在 HashTable 的底层的实现方中,都添加了
synchronized
关键字来确保线程同步,这也造成了 HashTable 的效率比更HashMap 低。在不考虑线程安全的情况下,优先使用HashMap;若需要考虑线程安全的问题,通常也是使用 Collections 工具包下的synchronizedMap
(底层也是通过加 synchronized 关键字确保线程安全)或者使用 Map 的子实现类ConcurrentHashMap
。(ConcurrentHashMap详解)
这是我在某个公司面试时被问到的问题,希望可以帮助到大家。