1、Hashtable 简介
1.1 介绍
和HashMap一样,Hashtable 也是一个散列表,它存储的内容是键值对(key-value)映射。
Hashtable 继承于Dictionary,实现了Map、Cloneable、java.io.Serializable接口。
Hashtable 的函数都是同步的,这意味着它是线程安全的。它的key、value都不可以为null。此外,Hashtable中的映射不是有序的。
1.2 构造
// 默认构造函数。
public Hashtable()
// 指定“容量大小”的构造函数
public Hashtable(int initialCapacity)
// 指定“容量大小”和“加载因子”的构造函数
public Hashtable(int initialCapacity, float loadFactor)
// 包含“子Map”的构造函数
public Hashtable(Map<? extends K, ? extends V> t)
1.3 继承关系
java.lang.Object
↳ java.util.Dictionary<K, V>
↳ java.util.Hashtable<K, V>
public class Hashtable<K,V> extends Dictionary<K,V>
implements Map<K,V>, Cloneable, java.io.Serializable { }
1.4 类图
2、源代码
public class Hashtable<K,V>
extends Dictionary<K,V>
implements Map<K,V>, Cloneable, java.io.Serializable {
private transient Entry<?,?>[] table;
//元素个数
private transient int count;
//临界值 元素个数超过则扩容 threshol=(int)(capacity * loadFactor)
private int threshold;
//加载因子
private float loadFactor;
//构造
public Hashtable(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal Load: "+loadFactor);
if (initialCapacity==0)
initialCapacity = 1;
this.loadFactor = loadFactor;
//新建Entry数组
table = new Entry<?,?>[initialCapacity];
threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
}
//有初始值的构造
public Hashtable(int initialCapacity) {
this(initialCapacity, 0.75f);
}
//默认构造
public Hashtable() {
this(11, 0.75f);
}
//包含“子Map”的构造函数
public Hashtable(Map<? extends K, ? extends V> t) {
this(Math.max(2*t.size(), 11), 0.75f);
putAll(t);
}
//获取key集合
public synchronized Enumeration<K> keys() {
return this.<K>getEnumeration(KEYS);
}
//获取value集合
public synchronized Enumeration<V> elements() {
return this.<V>getEnumeration(VALUES);
}
//根据key获取values
public synchronized V get(Object key) {
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.key.equals(key)) {
return (V)e.value;
}
}
return null;
}
//重新散列
protected void rehash() {
int oldCapacity = table.length;
Entry<?,?>[] oldMap = table;
// overflow-conscious code
//扩容 原长度的两倍
int newCapacity = (oldCapacity << 1) + 1;
if (newCapacity - MAX_ARRAY_SIZE > 0) {
if (oldCapacity == MAX_ARRAY_SIZE)
// Keep running with MAX_ARRAY_SIZE buckets
return;
newCapacity = MAX_ARRAY_SIZE;
}
//新建
Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];
modCount++;
//计算临界值
threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
table = newMap;
//遍历桶
for (int i = oldCapacity ; i-- > 0 ;) {
//遍历数组
for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) {
Entry<K,V> e = old;
old = old.next;
//计算新的下标
int index = (e.hash & 0x7FFFFFFF) % newCapacity;
//将元素放入index桶中,并将原桶中的元素放入链表
e.next = (Entry<K,V>)newMap[index];
newMap[index] = e;
}
}
}
//添加元素
private void addEntry(int hash, K key, V value, int index) {
modCount++;
Entry<?,?> tab[] = table;
//如果总数大于临界值 扩容
if (count >= threshold) {
// Rehash the table if the threshold is exceeded
rehash();
tab = table;
hash = key.hashCode();
index = (hash & 0x7FFFFFFF) % tab.length;
}
// Creates the new entry.
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>) tab[index];
//实际的添加
tab[index] = new Entry<>(hash, key, value, e);
count++;
}
//放入元素
public synchronized V put(K key, V value) {
// Make sure the value is not null
if (value == null) {
throw new NullPointerException();
}
// Makes sure the key is not already in the hashtable.
Entry<?,?> tab[] = table;
int hash = key.hashCode();
//计算key的下标
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> entry = (Entry<K,V>)tab[index];
//遍历
for(; entry != null ; entry = entry.next) {
//如果已存在key,替换value并返回,否则将遍历到链表末尾
if ((entry.hash == hash) && entry.key.equals(key)) {
V old = entry.value;
entry.value = value;
return old;
}
}
//实际的添加操作
addEntry(hash, key, value, index);
return null;
}
private transient volatile Set<K> keySet;
private transient volatile Set<Map.Entry<K,V>> entrySet;
//返回一个SynchronizedSet,且只有一个实例。SynchronizedSet是一个装饰者模式,使KeySet的方法线程安全
public Set<K> keySet() {
if (keySet == null)
keySet = Collections.synchronizedSet(new KeySet(), this);
return keySet;
}
//操作key的集
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();
}
}
//操作结果集
public Set<Map.Entry<K,V>> entrySet() {
if (entrySet==null)
//包装一层 使EntrySet的方法线程安全
entrySet = Collections.synchronizedSet(new EntrySet(), this);
return entrySet;
}
//对Map.Entry元素的操作
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 Collection<V> values() {
if (values==null)
values = Collections.synchronizedCollection(new ValueCollection(),
this);
return values;
}
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();
}
}
//节点元素类 单链表形式
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();
}
}
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;
//构造 type表示键/值标记
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 */
//查找下一个桶不为null的数据
while (e == null && i > 0) {
e = t[--i];
}
entry = e;
index = i;
//如果没有值返回false
return e != null;
}
@SuppressWarnings("unchecked")
//获取下一个数据
public T nextElement() {
Entry<?,?> et = entry;
int i = index;
Entry<?,?>[] t = table;
/* Use locals for faster loop iteration */
//遍历 获取下一个不为null的桶
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")
//桶中的首元素e
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();
}
}
}
}
2.2 遍历
public static void main(String[] args) {
Hashtable table = new Hashtable();
Object key, value;
//获取Map.Entry的Set集的迭代器
Iterator iter = table.entrySet().iterator();
while(iter.hasNext()) {
Map.Entry entry = (Map.Entry)iter.next();
key = entry.getKey();
value = entry.getValue();
}
//key集
Iterator iter1 = table.keySet().iterator();
while (iter1.hasNext()) {
// 获取key
key = iter1.next();
// 根据key,获取value
value = table.get(key);
}
//结果集
Collection c = table.values();
Iterator iter2= c.iterator();
while (iter2.hasNext()) {
value = iter2.next();
}
//Enumeration的key集
Enumeration keys = table.keys();
while(keys.hasMoreElements()) {
key = keys.nextElement();
}
//Enumeration的value集
Enumeration values = table.elements();
while(values.hasMoreElements()) {
value = values.nextElement();
}
}
2.3 总结
1、Hashtable是线程安全的
2、Hashtable支持fail-fast
3、Hashtable的key和value都不能为null(参加put方法 如果key为null,计算hashCode会报错)
4、Hashtable的容量不再是2的次方,默认是11。且每次扩容为*2+1
5、计算下标时,使用(hashCode&0x7FFFFFFF)%len,&0x7FFFFFFF可以消去hash最高位的1(如果有的话),保证hash为正