之前分析过HashMap的结构,接下来简单的分析一下HashTable的数据结构和线程安全的实现。
HashTable实现上与HashMap实现的数据结构相似,先看HashTable定义:
public class Hashtable<K,V>
extends Dictionary<K,V>
implements Map<K,V>, Cloneable, java.io.Serializable {
它实现了Map接口,与HashMap不一样的是,他继承了Dictionary。那么接下来看一下他的主要成员变量:
private transient Entry<K,V>[] table;
private transient int count;
private int threshold;
private float loadFactor;
与HashMap类似,他拥有一个hash的表table数组,同时定义了装载因子loadFactor,初始化桶容量threshold,接下来看一下HashTable重写的Entry:
private static class Entry<K,V> implements Map.Entry<K,V> {
int hash;
final K key;
V value;
Entry<K,V> next;
...
}
与HashMap类似的他将Entry定义为一个存储key-map的链表结构。那么我们可以继续仿照HashMap去理解HashTable的结构。
接下来,我们看一下HashTable中的put方法:
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 = hash(key);
int index = (hash & 0x7FFFFFFF) % tab.length;
for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
if ((e.hash == hash) && e.key.equals(key)) {
V old = e.value;
e.value = value;
return old;
}
}
modCount++;
if (count >= threshold) {
// Rehash the table if the threshold is exceeded
rehash();
tab = table;
hash = hash(key);
index = (hash & 0x7FFFFFFF) % tab.length;
}
// Creates the new entry.
Entry<K,V> e = tab[index];
tab[index] = new Entry<>(hash, key, value, e);
count++;
return null;
}
第一眼看上去,好长,而且在一个方法内实现了大部分的逻辑,可以看出,HashTable在实现数据结构层面上没有HashMap的精炼,算法层面上也没有HashMap写的优。一部分原因是这部分代码实现在JDK1.0中,另一方面,是为了保持操作的原子性,保证线程安全。可以看到,HashTable在实现线程安全方面,通过将读写操作代码整合在一个方法中,通过synchronized来达到线程互斥,保证线程安全。
那么看一下HashTable中还有哪些通过synchronized声明的方法:
synchronized void clear()
synchronized Object clone()
synchronized boolean contains(Object value)
synchronized boolean containsKey(Object key)
synchronized boolean containsValue(Object value)
synchronized Enumeration<V> elements()
synchronized Set<Entry<K, V>> entrySet()
synchronized boolean equals(Object object)
synchronized V get(Object key)
synchronized int hashCode()
synchronized boolean isEmpty()
synchronized Set<K> keySet()
synchronized Enumeration<K> keys()
synchronized V put(K key, V value)
synchronized void putAll(Map<? extends K, ? extends V> map)
synchronized V remove(Object key)
synchronized int size()
synchronized String toString()
synchronized Collection<V> values()
通过分析put方法大致发现了HashTable在实现线程安全方面采取了一些有别于HashMap的方式,其他的方法可以大致参考HashMap的解释,就懒一下,不分析了。
网友评论