一、HashMap 和 HashTable 的概述
(一)、HashMap:
(1)由数组+链表组成的,基于哈希表的Map实现,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的。
(2)不是线程安全的,HashMap可以接受为null的键(key)和值(value)。
(3)HashMap重新计算hash值
(二)、Hashtable:
(1)Hashtable 是一个散列表,它存储的内容是键值对(key-value)映射。
(2)Hashtable 的函数都是同步的,这意味着它是线程安全的。它的key、value都不可以为null。
(3)HashTable直接使用对象的hashCode。
二、HashMap 和 HashTable 的区别
- 1、继承和实现不同
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
-
2、对null值的支持不同
HashMap:key可以为null,但是只能有一个,,因为必须保证key的唯一性;可以有多个key值对应的value为null。
HashTable:key和value都不能为null。
-
3、安全性不同
Hashtable 是线程安全的,它的每个方法上都有 synchronized 关键字,因此可直接用于多线程中。虽然 HashMap 是线程不安全的,但是它的效率远远高于 Hashtable,这样设计是合理的,因为大部分的使用场景都是单线程。当需要多线程操作的时候可以使用线程安全的 ConcurrentHashMap。ConcurrentHashMap 虽然也是线程安全的,但是它的效率比 Hashtable 要高好多倍。因为ConcurrentHashMap 使用了分段锁,并不对整个数据进行锁定。
HashMap 是线程不安全的,在多线程并发的环境下,可能会产生死锁等问题,因此需要自己处理多线程的安全问题。
-
4、hash值不同
①、Hashtable计算hash值,直接用key的hashCode(),而HashMap重新计算了key的hash值。
-
5、内部实现使用的数组初始化和扩容方式不同
①、HashTable在不指定容量的情况下的默认容量为11,而HashMap为16,Hashtable不要求底层数组的容量一定要为2的整数次幂,而HashMap则要求一定为2的整数次幂。
②、Hashtable扩容时,将容量变为原来的2倍加1,而HashMap扩容时,将容量变为原来的2倍。
- 6、对外提供的方法不同
Hashtable 比 HashMap 多提供了 elments() 和 contains() 两个方法。
①、elments() 方法继承自 Hashtable 的父类 Dictionnary。elements() 方法用于返回此 Hashtable 中的 value 的枚举。
public synchronized Enumeration<V> elements() {
return this.<V>getEnumeration(VALUES);
}
②、contains()方法判断该 Hashtable 是否包含传入的 value。它的作用与 containsValue()一致。事实上,contansValue() 就只是调用了一下 contains() 方法。
public synchronized boolean contains(Object value) {
if (value == null) {
throw new NullPointerException();
}
Entry<?,?> tab[] = table;
for (int i = tab.length ; i-- > 0 ;) {
for (Entry<?,?> e = tab[i] ; e != null ; e = e.next) {
if (e.value.equals(value)) {
return true;
}
}
}
return false;
}