0.出现时间?
HashMap是jdk1.2
Hashtable是jdk1.1
HashMap出现得晚
1.线程安全?
HashMap线程不安全 Collections.synchronizedMap(map);
Hashtable线程安全 synchronized
2.null key?
HashMap允许 null key。但是,null key只能有一个,null value可以有多个
Hashtable不允许null key 和 null value,空指针异常
由于HashMap允许null值,因此,当get(key)返回null时,两种情况:
该key对应的value为null
map中不存在该key
因此,判断一个map中是否含有key时,应使用containsKey(key)
3.父类
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable
public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, java.io.Serializable
继承的父类不同,实现的接口相同
Dictionary是一个已经废弃的类
4.初始容量、加载因子
HashMap:
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
static final int MAXIMUM_CAPACITY = 1 << 30;
static final float DEFAULT_LOAD_FACTOR = 0.75f;
扩容:resize(2 * table.length);
HashMap的长度总是2的n次方。
如果在创建HashMap对象时,指定了初始大小,并且该大小不是2的n次方时,会自动调整为比指定值大的最接近的2的n次方;如果指定的初始大小大于MAXIMUM_CAPACITY ,则初始为MAXIMUM_CAPACITY
public HashMap() {
this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
}
Hashtable:
初始:11
加载因子:0.75F
int newCapacity = (oldCapacity << 1) + 1;
HashTable的总长度会尽量使用素数、奇数。
如果在创建Hashtable对象时,手动指定了初始化大小,就直接使用给定的值
public Hashtable() {
this(11, 0.75f);
}
5.hashCode计算
当哈希表的长度为素数(Hashtable)时,取模的结果更均匀,冲突少
当哈希表的长度为2的幂可以使用位运算得到结果,位运算效率高,由于使用2的幂长度的哈希表,冲突增加,所以,HashMap在得到key的hashcode之后,有做了一些处理,使冲突减少
HashMap
int hash = hash(key);// 在得到对象的hash值之后,通过一系列的位运算打散数据,减少hash冲突
int i = indexFor(hash, table.length); return h & (length-1);// 使用位运算得到键值对存储的位置
Hashtable
int hash = hash(key);// 计算key的哈希值,就是对象的hash值
int index = (hash & 0x7FFFFFFF) % tab.length;// 哈希表的长度是素数或者奇数,直接取余就是该键值对在哈希表中存储的位置
6.底层实现
1.7都是数组+链表
private transient Entry<K,V>[] table;
HashMap 和 Hashtable 底层都是Entry<K,V>(内部类)
HashMap:static class Entry<K,V> implements Map.Entry<K,V>
Hashtable:private static class Entry<K,V> implements Map.Entry<K,V>
7.遍历方式
Iterator
Hashtable还使用了Enumeration
HashMap的Iterator是fail-fast迭代器
JDK8之前,Hashtable是没有fast-fail机制的。JDK8 ,HashTable也是使用fast-fail的
当有其它线程改变了HashMap的结构(增加,删除,修改元素),将会抛出ConcurrentModificationException。不过,通过Iterator的remove()方法移除元素则不会抛出ConcurrentModificationException异常。
8.API
Hashtable比HashMap多两个public 方法
elements()这个方法来自于抽象类Dictionary,该类已经废弃。
contains() containsValue()方法内部调用了该方法,实现的是同样的功能
public boolean containsValue(Object value) {
return contains(value);
}