简单看一下 HashTable 内部结构java
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; private int threshold; private float loadFactor; private transient int modCount = 0; 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; 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); } public Hashtable(Map<? extends K, ? extends V> t) { this(Math.max(2*t.size(), 11), 0.75f); putAll(t); } public synchronized int size() {...} public synchronized boolean isEmpty() {...} public synchronized Enumeration<K> keys() {...} public synchronized Enumeration<V> elements() {...} public synchronized boolean contains(Object value) {...} public synchronized boolean containsKey(Object key) {...} 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(); } } 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; } 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(); int index = (hash & 0x7FFFFFFF) % tab.length; @SuppressWarnings("unchecked") Entry<K,V> entry = (Entry<K,V>)tab[index]; for(; entry != null ; entry = entry.next) { if ((entry.hash == hash) && entry.key.equals(key)) { V old = entry.value; entry.value = value; return old; } } addEntry(hash, key, value, index); return null; } public synchronized V remove(Object key) { 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.key.equals(key)) { modCount++; if (prev != null) { prev.next = e.next; } else { tab[index] = e.next; } count--; V oldValue = e.value; e.value = null; return oldValue; } } return null; } public synchronized void putAll(Map<? extends K, ? extends V> t) {...} public synchronized void clear() {...} public synchronized Object clone() {...} public synchronized String toString() {...} .... }
看过 HashMap 内部结构以后再来看 HashTable,就会发现结构很是类似。数组
默认构造方法初始化容量为11,负载因子为0.75,几乎全部的方法都用了 synchronized 修饰了,全部的操做都须要把整个map锁起来,数据是很是安全的,在多线程状况下不会有什么问题,可是性能应该也不怎么样。安全
HashTable 肯定一个数组的位置用的方法为多线程
int index = (hash & 0x7FFFFFFF) % tab.length;
hash 值可能为负数,0x7FFFFFFF的意思是首位为0 剩下的都是1。二进制的第一位为符号为,hash & 0x7FFFFFFF % tab.length 的意思也就是把hash值转换为正数在和tab.length取模,获得数组的位置。性能
get/put/remove 都是先锁方法,而后经过这个方法获取位置,再对位置上的节点操做。this
Java Collections Framework</a>. Unlike the new collection
implementations, {@code Hashtable} is synchronized. If a
thread-safe implementation is not needed, it is recommended to use
{@link HashMap} in place of {@code Hashtable}. If a thread-safe
highly-concurrent implementation is desired, then it is recommended
to use {@link java.util.concurrent.ConcurrentHashMap} in place of
{@code Hashtable}..net
这是官网注解,若是不须要线程安全的话,用 HashMap。若是须要线程安全的话,用 ConcurrentHashMap。线程