A.HashMap不加synchronized,Hashtable加synchronized
B.HashMap允许Key和Value为null,而Hashtable不允许
C.由于synchronized原因,HashMap效率比Hashtable高,但是Hashtable比HashMap安全
我们来分析一下源码:
1.HashMap
2.HashTable
/**
* The hash table.
*/
private transient HashtableEntry<K, V>[] table;
一个HashtableEntry的数组。
/**
* Note: technically the methods of this class should synchronize the
* backing map. However, this would require them to have a reference
* to it, which would cause considerable bloat. Moreover, the RI
* behaves the same way.
*/
private static class HashtableEntry<K, V> implements Entry<K, V> {
final K key;
V value;
final int hash;
HashtableEntry<K, V> next;
HashtableEntry(K key, V value, int hash, HashtableEntry<K, V> next) {
this.key = key;
this.value = value;
this.hash = hash;
this.next = next;
}
public final K getKey() {
return key;
}
public final V getValue() {
return value;
}
public final V setValue(V value) {
if (value == null) {
throw new NullPointerException("value == null");
}
V oldValue = this.value;
this.value = value;
return oldValue;
}
@Override public final boolean equals(Object o) {
if (!(o instanceof Entry)) {
return false;
}
Entry<?, ?> e = (Entry<?, ?>) o;
return key.equals(e.getKey()) && value.equals(e.getValue());
}
@Override public final int hashCode() {
return key.hashCode() ^ value.hashCode();
}
@Override public final String toString() {
return key + "=" + value;
}
}
这个HashtableEntry有个next指针指向下一个结点,看起来像个链表。
/**
* Constructs a new {@code Hashtable} using the default capacity and load
* factor.
*/
@SuppressWarnings("unchecked")
public Hashtable() {
table = (HashtableEntry<K, V>[]) EMPTY_TABLE;
threshold = -1; // Forces first put invocation to replace EMPTY_TABLE
}
构造函数中对链表进行初始化。
/**
* Associate the specified value with the specified key in this
* {@code Hashtable}. If the key already exists, the old value is replaced.
* The key and value cannot be null.
*
* @param key
* the key to add.
* @param value
* the value to add.
* @return the old value associated with the specified key, or {@code null}
* if the key did not exist.
* @see #elements
* @see #get
* @see #keys
* @see java.lang.Object#equals
*/
public synchronized V put(K key, V value) {
if (key == null) {
throw new NullPointerException("key == null");
} else if (value == null) {
throw new NullPointerException("value == null");
}
int hash = Collections.secondaryHash(key);
HashtableEntry<K, V>[] tab = table;
int index = hash & (tab.length - 1);
HashtableEntry<K, V> first = tab[index];
for (HashtableEntry<K, V> e = first; e != null; e = e.next) {
if (e.hash == hash && key.equals(e.key)) {
V oldValue = e.value;
e.value = value;
return oldValue;
}
}
// No entry for key is present; create one
modCount++;
if (size++ > threshold) {
rehash(); // Does nothing!!
tab = doubleCapacity();
index = hash & (tab.length - 1);
first = tab[index];
}
tab[index] = new HashtableEntry<K, V>(key, value, hash, first);
return null;
}
添加数据时加锁。而HashMap是不加锁的。首先通过next指针判断链表中是否已经存在该元素,如果存在,则更新为新的元素。然后如果链表中没有该元素,则添加到链表的某一位置。这个既是数组又是链表的数据结构结合了查找和插入/删除的优点。其中的hash函数需要了解了解。