類 Hashtable
此類實現一個哈希表,該哈希表將鍵映射到相應的值。任何非 null 對象都可以用作鍵或值。
爲了成功地在哈希表中存儲和檢索對象,用作鍵的對象必須實現 hashCode 方法和 equals 方法。
Hashtable 的實例有兩個參數影響其性能:初始容量 和加載因子。容量 是哈希表中桶 的數量,初始容量 就是哈希表創建時的容量。注意,哈希表的狀態爲 open:在發生“哈希衝突”的情況下,單個桶會存儲多個條目,這些條目必須按順序搜索。加載因子 是對哈希表在其容量自動增加之前可以達到多滿的一個尺度。初始容量和加載因子這兩個參數只是對該實現的提示。關於何時以及是否調用 rehash 方法的具體細節則依賴於該實現。
通常,默認加載因子(.75)在時間和空間成本上尋求一種折衷。加載因子過高雖然減少了空間開銷,但同時也增加了查找某個條目的時間(在大多數 Hashtable 操作中,包括 get 和 put 操作,都反映了這一點)。
初始容量主要控制空間消耗與執行 rehash 操作所需要的時間損耗之間的平衡。如果初始容量大於 Hashtable 所包含的最大條目數除以加載因子,則永遠 不會發生 rehash 操作。但是,將初始容量設置太高可能會浪費空間。
如果很多條目要存儲在一個 Hashtable 中,那麼與根據需要執行自動 rehashing 操作來增大表的容量的做法相比,使用足夠大的初始容量創建哈希表或許可以更有效地插入條目。
Hashtable 是同步的。
源碼
Hashtable繼承自Dictionary<K,V>,實現了返回所有key和所有value的枚舉類的方法:
public synchronized Enumeration<K> keys() {
return this.<K>getEnumeration(KEYS);
}
public synchronized Enumeration<V> elements() {
return this.<V>getEnumeration(VALUES);
}
內部的迭代器以及枚舉類都由內部類Enumerator實現:
private static final int KEYS = 0;
private static final int VALUES = 1;
private static final int ENTRIES = 2;
private class Enumerator<T> implements Enumeration<T>, Iterator<T> {
Entry[] table = Hashtable.this.table;
int index = table.length;
Entry<K,V> entry = null;
Entry<K,V> lastReturned = null;
int type;
/**
* Indicates whether this Enumerator is serving as an Iterator
* or an Enumeration. (true -> Iterator).
*/
boolean iterator;
/**
* The modCount value that the iterator believes that the backing
* Hashtable should have. If this expectation is violated, the iterator
* has detected concurrent modification.
*/
protected int expectedModCount = modCount;
Enumerator(int type, boolean iterator) {
this.type = type;
this.iterator = iterator;
}
public boolean hasMoreElements() {
Entry<K,V> e = entry;
int i = index;
Entry[] t = table;
/* Use locals for faster loop iteration */
while (e == null && i > 0) {
e = t[--i];
}
entry = e;
index = i;
return e != null;
}
public T nextElement() {
Entry<K,V> et = entry;
int i = index;
Entry[] t = table;
/* Use locals for faster loop iteration */
while (et == null && i > 0) {
et = t[--i];
}
entry = et;
index = i;
if (et != null) {
Entry<K,V> e = lastReturned = entry;
entry = e.next;
return type == KEYS ? (T)e.key : (type == VALUES ? (T)e.value : (T)e);
}
throw new NoSuchElementException("Hashtable Enumerator");
}
// Iterator methods
public boolean hasNext() {
return hasMoreElements();
}
public T next() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
return nextElement();
}
public void remove() {
if (!iterator)
throw new UnsupportedOperationException();
if (lastReturned == null)
throw new IllegalStateException("Hashtable Enumerator");
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
synchronized(Hashtable.this) {
Entry[] tab = Hashtable.this.table;
int index = (lastReturned.hash & 0x7FFFFFFF) % tab.length;
for (Entry<K,V> e = tab[index], prev = null; e != null;
prev = e, e = e.next) {
if (e == lastReturned) {
modCount++;
expectedModCount++;
if (prev == null)
tab[index] = e.next;
else
prev.next = e.next;
count--;
lastReturned = null;
return;
}
}
throw new ConcurrentModificationException();
}
}
}
與HashMap的比較
Hashtable的鍵和值都不能爲null。
提供的所有方法都是同步的。
無序的。
Hashtable默認的初始大小爲11,之後每次擴充,容量變爲原來的2n+1。HashMap默認的初始化大小爲11,之後每次擴充,容量變爲原來的2倍。
計算hash值的方法不同 。