持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情
源码
public class Hashtable<K,V>
extends Dictionary<K,V>
implements Map<K,V>, Cloneable, java.io.Serializable {
}
注释内容
- 这个类实现 hash table,映射 key 到 value。任何 non-null 对象能够被用作 key 或 value
- 要从 hash table 成功存储和检索,用作 key 的对象必须实现 hashCode 和 equals 方法
- Hashtable 实例有两个影响性能的参数:initial capacity 和 load factor。capacity 是 hash table 中 buckets 的数量,initial capacity 只是 hash table 创建时的容量。请注意,hash table 是 open:在“哈希冲突”的情况下,单个 bucket 存储多个 entry,必须按顺序搜索。load factor 是在自动增加它的容量之前,允许 hash table 多满的估量。initial capacity 和 load factor 参数仅仅是对实现的提示。何时和如何调用 rehash 方法明确细节取决于实现
- 通常,默认load factor(0.75)在时间和空间成本提供好的平衡。更高的值减少空间开销,但增加查找 entry 的时间花费(影响大多数 Hashtable 操作,包括 get 和 put)
- initial capacity 控制浪费空间和需要 rehash 操作的平衡,这很耗时。如果 initial capacity 大于 Hashtable 中 entries 的最大值除以它的 load factor,不会再发生 rehash 操作。然而,设置 initial capacity 太高会浪费空间
- 如果要在 Hsahtable 创建很多 entry,使用一个非常大容量的创建它,可以允许更高效地插入 entry,而不是让它根据需要自动执行重新哈希去增大表
- 这个例子创建一个数字的 hashtable。它使用数字的名称作为 key
ashtable<String, Integer> numbers = new Hashtable<String, Integer>();
numbers.put("one", 1);
numbers.put("two", 2);
numbers.put("three", 3);
- 检索数字,使用下面的代码
Integer n = numbers.get("two");
if (n != null) {
System.out.println("two = " + n);
}
- 这个类所有的“集合视图方法”返回的集合的 iterator 方法返回的迭代器是 fail-fast。如果在 iterator 被创建后,除了通过迭代器自己的 remove 方法,用任何方式修改 Hashtable 结构,迭代器将抛出 ConcurrentModificationException。因此,面对并发修改,iterator 快速和干净地失败,而不是在未来不确定的时间冒着任意的,不确定的操作的风险。Hashtable 的 keys 和 elements 方法返回的 Enumerations 不是 fail-fast
- 注意:iterator 的 fail-fast 行为不能确保,一般来说,不可能在非同步的并发修改的情况做任何硬保证。Fail-fast 迭代器最大努力抛出 ConcurrentModificationException。因此,写一个依赖这个异常的正确性的程序是错误的:iterators 的 fail-fast 行为应该只被用于检测 bug
- 从 Java 2 平台 v1.2 这个类改造为实现 Map 接口,让它作为 Java Collections Framework 的一员。不像新的集合实现,Hashtable 是同步的。如果不需要线程安全实现,推荐使用 HashMap 代替 Hashtable。如果渴望线程安全高度并发的实现,那么建议使用 ConcurrentHashMap 代替 Hashtable
KeySet
public class Hashtable<K, V>
extends Dictionary<K, V>
implements Map<K, V>, Cloneable, java.io.Serializable {
private class KeySet extends AbstractSet<K> {
public Iterator<K> iterator() {
return getIterator(KEYS);
}
public int size() {
return count;
}
public boolean contains(Object o) {
return containsKey(o);
}
public boolean remove(Object o) {
return Hashtable.this.remove(o) != null;
}
public void clear() {
Hashtable.this.clear();
}
}
}
EntrySet
public class Hashtable<K,V>
extends Dictionary<K,V>
implements Map<K,V>, Cloneable, java.io.Serializable {
private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
public Iterator<Map.Entry<K,V>> iterator() {
return getIterator(ENTRIES);
}
public boolean add(Map.Entry<K,V> o) {
return super.add(o);
}
public boolean contains(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?,?> entry = (Map.Entry<?,?>)o;
Object key = entry.getKey();
Entry<?,?>[] tab = table;
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
for (Entry<?,?> e = tab[index]; e != null; e = e.next)
if (e.hash==hash && e.equals(entry))
return true;
return false;
}
public boolean remove(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?,?> entry = (Map.Entry<?,?>) o;
Object key = entry.getKey();
Entry<?,?>[] tab = table;
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)tab[index];
for(Entry<K,V> prev = null; e != null; prev = e, e = e.next) {
if (e.hash==hash && e.equals(entry)) {
modCount++;
if (prev != null)
prev.next = e.next;
else
tab[index] = e.next;
count--;
e.value = null;
return true;
}
}
return false;
}
public int size() {
return count;
}
public void clear() {
Hashtable.this.clear();
}
}
}
ValueCollection
public class Hashtable<K, V>
extends Dictionary<K, V>
implements Map<K, V>, Cloneable, java.io.Serializable {
private class ValueCollection extends AbstractCollection<V> {
public Iterator<V> iterator() {
return getIterator(VALUES);
}
public int size() {
return count;
}
public boolean contains(Object o) {
return containsValue(o);
}
public void clear() {
Hashtable.this.clear();
}
}
}
Entry
public class Hashtable<K, V>
extends Dictionary<K, V>
implements Map<K, V>, Cloneable, java.io.Serializable {
/**
* Hashtable bucket collision list entry
*/
private static class Entry<K, V> implements Map.Entry<K, V> {
final int hash;
final K key;
V value;
Entry<K, V> next;
protected Entry(int hash, K key, V value, Entry<K, V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
@SuppressWarnings("unchecked")
protected Object clone() {
return new Entry<>(hash, key, value,
(next == null ? null : (Entry<K, V>) next.clone()));
}
// Map.Entry Ops
public K getKey() {
return key;
}
public V getValue() {
return value;
}
public V setValue(V value) {
if (value == null)
throw new NullPointerException();
V oldValue = this.value;
this.value = value;
return oldValue;
}
public boolean equals(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
return (key == null ? e.getKey() == null : key.equals(e.getKey())) &&
(value == null ? e.getValue() == null : value.equals(e.getValue()));
}
public int hashCode() {
return hash ^ Objects.hashCode(value);
}
public String toString() {
return key.toString() + "=" + value.toString();
}
}
}
Enumerator
public class Hashtable<K, V>
extends Dictionary<K, V>
implements Map<K, V>, Cloneable, java.io.Serializable {
/**
* A hashtable enumerator class. This class implements both the
* Enumeration and Iterator interfaces, but individual instances
* can be created with the Iterator methods disabled. This is necessary
* to avoid unintentionally increasing the capabilities granted a user
* by passing an Enumeration.
*/
private class Enumerator<T> implements Enumeration<T>, Iterator<T> {
Entry<?, ?>[] table = Hashtable.this.table;
int index = table.length;
Entry<?, ?> entry;
Entry<?, ?> lastReturned;
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<?, ?> 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;
}
@SuppressWarnings("unchecked")
public T nextElement() {
Entry<?, ?> 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<?, ?> 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;
@SuppressWarnings("unchecked")
Entry<K, V> e = (Entry<K, V>) tab[index];
for (Entry<K, V> 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();
}
}
}
}
注释内容
- hashtable 枚举类。这个类实现了 Enumeration 和 Iterator 接口,但可以在禁用 Iterator 方法时创建单个实例。避免通过传递 Enumeration 无意中增加授予用户的能力是必要的
字段
boolean iterator:表明这个 Enumerator 作为 Iterator 或者 Enumeration(true -> Iterator)protected int expectedModCount = modCount:iterator 相信支持 Hashtable 应该有 modCount 值。如果违反这个预期,iterator 发现并发修改