HashTable
的方式使用 synchronized
修饰以保证线程安全,相比 HashMap
来说优化策略少。由于 HashTable
的实现相当原始,源码没有阅读难度。
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); } // 默认构造方法,初始容量为11,初始负载因子为0.75 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); } Hashtable(Void dummy) {}
// 查找是否有指定值 public synchronized boolean contains(Object value) { // 不支持value为null if (value == null) { throw new NullPointerException(); } // 遍历哈希表,查找是否有指定值 Entry<?,?> tab[] = table; // 从哈希表的拉链首元素开始往后遍历 for (int i = tab.length ; i-- > 0 ;) { for (Entry<?,?> e = tab[i] ; e != null ; e = e.next) { // 直到找到对应值 if (e.value.equals(value)) { return true; } } } return false; } // 查找是否有指定key public synchronized boolean containsKey(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) { // 匹配哈希值且key完全相同 if ((e.hash == hash) && e.key.equals(key)) { return true; } } return false; // 不匹配 }
// 获取指定key的value,没有则返回null @SuppressWarnings("unchecked") public synchronized V get(Object key) { Entry<?,?> tab[] = table; int hash = key.hashCode(); // 计算key的哈希值 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; // 没有匹配到指定key,返回null的value } // 获取指定key的value,没有则返回defaultValue @Override public synchronized V getOrDefault(Object key, V defaultValue) { // 依赖get(key)方法,然后看是否为null再返回defaultValue V result = get(key); return (null == result) ? defaultValue : result; }
// 数组最大长度 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; // 扩容并冲哈希所有键值 @SuppressWarnings("unchecked") protected void rehash() { int oldCapacity = table.length; Entry<?,?>[] oldMap = table; // 上溢检查 int newCapacity = (oldCapacity << 1) + 1; if (newCapacity - MAX_ARRAY_SIZE > 0) { if (oldCapacity == MAX_ARRAY_SIZE) // 已经到达最大值,不能再扩容 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; // 计算新哈希桶索引 e.next = (Entry<K,V>)newMap[index]; // 这里两行相当于头插法插入链表 newMap[index] = e; } } }
private void addEntry(int hash, K key, V value, int index) { Entry<?,?> tab[] = table; if (count >= threshold) { // 超过阀值大小,哈希表执行扩容 rehash(); tab = table; hash = key.hashCode(); // 取键的哈希值 index = (hash & 0x7FFFFFFF) % tab.length; // 算哈希索引 } // 创建新的Entry,存入key和value @SuppressWarnings("unchecked") Entry<K,V> e = (Entry<K,V>) tab[index]; tab[index] = new Entry<>(hash, key, value, e); // 把Entry放入哈希索引中 count++; // 总数递增 modCount++; // 修改次数递增 } public synchronized V put(K key, V value) { if (value == null) { throw new NullPointerException(); } 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) { if ((entry.hash == hash) && entry.key.equals(key)) { // 如果已存在相同key的Enty,则替换该Entry的value V old = entry.value; entry.value = value; return old; // 返回旧的value } } // 不存在该Entry,创建新Entry addEntry(hash, key, value, index); return null; // 创建新的Entry就一定返回null作为value } // 递归调用put() public synchronized void putAll(Map<? extends K, ? extends V> t) { for (Map.Entry<? extends K, ? extends V> e : t.entrySet()) put(e.getKey(), e.getValue()); } // 仅在key对应的Entry不存在的时候才创建的新Entry,否则直接返回旧value @Override public synchronized V putIfAbsent(K key, V value) { Objects.requireNonNull(value); 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)) { // 从拉链匹配对应Entry V old = entry.value; // 旧value为null,直接放入 if (old == null) { entry.value = value; } return old; // 直接返回oldValue } } // 没有旧的Entry,创建新的并存入 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) { // 哈希值相同,且key相同 if ((e.hash == hash) && e.key.equals(key)) { // 节点从链表中解除引用 if (prev != null) { prev.next = e.next; // 中间节点解除引用 } else { tab[index] = e.next; // 头结点解除引用 } modCount++; // 修改递增 count--; // 元素数量递减 V oldValue = e.value; // 获取旧值 e.value = null; // 置空回收 return oldValue; } } return null; // key匹配不到Entry } // 参考删除方法,此方法只是增加检查value是否一致,仅在一致的时候才移除 @Override public synchronized boolean remove(Object key, Object value) { Objects.requireNonNull(value); 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) && e.value.equals(value)) { if (prev != null) { prev.next = e.next; } else { tab[index] = e.next; } e.value = null; // 置空以便GC modCount++; count--; return true; } } return false; } // 清空哈希表的所有元素,表长度不会改变 public synchronized void clear() { Entry<?,?> tab[] = table; for (int index = tab.length; --index >= 0; ) tab[index] = null; modCount++; count = 0; }
public synchronized boolean equals(Object o) { if (o == this) return true; if (!(o instanceof Map)) return false; Map<?,?> t = (Map<?,?>) o; if (t.size() != size()) return false; try { for (Map.Entry<K, V> e : entrySet()) { K key = e.getKey(); V value = e.getValue(); if (value == null) { if (!(t.get(key) == null && t.containsKey(key))) return false; } else { if (!value.equals(t.get(key))) return false; } } } catch (ClassCastException unused) { return false; } catch (NullPointerException unused) { return false; } return true; } public synchronized int hashCode() { int h = 0; if (count == 0 || loadFactor < 0) return h; // 返回0 loadFactor = -loadFactor; Entry<?,?>[] tab = table; for (Entry<?,?> entry : tab) { while (entry != null) { h += entry.hashCode(); entry = entry.next; } } loadFactor = -loadFactor; return h; }
@Override public synchronized boolean replace(K key, V oldValue, V newValue) { Objects.requireNonNull(oldValue); Objects.requireNonNull(newValue); 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 (; e != null; e = e.next) { if ((e.hash == hash) && e.key.equals(key)) { // 查找是否有key对应的Entry if (e.value.equals(oldValue)) { e.value = newValue; // 同时还有oldValue匹配,才能替换为newValue return true; // 替换成功 } else { return false; // 替换失败 } } } return false; } // 用key查找对应Entry,并替换oldValue为value @Override public synchronized V replace(K key, V value) { Objects.requireNonNull(value); 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 (; e != null; e = e.next) { // 逐个遍历,查找是否有对应Entry if ((e.hash == hash) && e.key.equals(key)) { V oldValue = e.value; e.value = value; return oldValue; // 返回旧值 } } return null; // 没有对应key,返回null }
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; } // Clone @SuppressWarnings("unchecked") protected Object clone() { return new Entry<>(hash, key, value, (next==null ? null : (Entry<K,V>) next.clone())); } // 获取键 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(); } }
上一篇
Java源码系列(9) -- HashMap