Hashtable简介
Hashtable基于哈希表实现的,每个元素都是key-value对,通过单链表解决哈希冲突。
Hashtable是线程安全的,实现Serializable可以序列化,实现Cloneable接口,能被克隆。
源码
package java.util;
import java.io.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.BiFunction;
import jdk.internal.access.SharedSecrets;
public class Hashtable<K,V>
extends Dictionary<K,V>
implements Map<K,V>, Cloneable, java.io.Serializable {
// 保存key-value对的数组
private transient Entry<?,?>[] table;
// key-value的数量
private transient int count;
// 超过这个值就扩容(threshold=容量*loadfactor)
private int threshold;
// 加载因子 默认0.75根hashMap一样
private float loadFactor;
// 被改变的次数
private transient int modCount = 0;
// 序列版本号
private static final long serialVersionUID = 1421746759512286392L;
// 指定容量大小和加载因子的构造函数
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.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); //全部元素添加过来
}
Hashtable(Void dummy) {}
// key-value的数量
public synchronized int size() {
return count;
}
// 为空
public synchronized boolean isEmpty() {
return count == 0;
}
// 返回key的枚举对象
public synchronized Enumeration<K> keys() {
return this.<K>getEnumeration(KEYS);
}
// 返回value的枚举对象
public synchronized Enumeration<V> elements() {
return this.<V>getEnumeration(VALUES);
}
// 判断Hashtable所有key-value中value是否包含 这个value
public synchronized boolean contains(Object value) {
// 如果value为null就抛出异常
if (value == null) {
throw new NullPointerException();
}
// 从后往前遍历所有key-value
Entry<?,?> tab[] = table;
for (int i = tab.length ; i-- > 0 ;) {
// Entry为单链表,循环遍历,判断当前节点是否为value
for (Entry<?,?> e = tab[i] ; e != null ; e = e.next) {
if (e.value.equals(value)) {
return true;
}
}
}
return false;
}
public boolean containsValue(Object value) {
return contains(value);
}
// 判断key-value对中是否存在这样一个key
public synchronized boolean containsKey(Object key) {
Entry<?,?> tab[] = table;
// 计算key的hash值
int hash = key.hashCode();
// 算出在table中的位置
int index = (hash & 0x7FFFFFFF) % tab.length;
// 取出该位置的Entry(单链表)hash值和key值都相等的元素是否存在
for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
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();
// 计算下标
int index = (hash & 0x7FFFFFFF) % tab.length;
// 在这个key所对应的链表中找出一个hash值和key值都相等的元素
for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
if ((e.hash == hash) && e.key.equals(key)) {
return (V)e.value;
}
}
return null;
}
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
// Hashtable的扩容
@SuppressWarnings("unchecked")
protected void rehash() {
int oldCapacity = table.length;
Entry<?,?>[] oldMap = table;
// 扩容为原来的2倍+1
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;
}
// 创建新容量大小的table
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;
重新计算index
int index = (e.hash & 0x7FFFFFFF) % newCapacity;
e.next = (Entry<K,V>)newMap[index];
newMap[index] = e;
}
}
}
// 在index处插入key-value
private void addEntry(int hash, K key, V value, int index) {
Entry<?,?> tab[] = table;
// 超过阀值要扩容
if (count >= threshold) {
// Rehash the table if the threshold is exceeded
rehash();
tab = table;
hash = key.hashCode(); // 重新计算hash值
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); // 将新的节点插入到tab[index]处链的头部
count++;
modCount++;
}
// 添加元素
public synchronized V put(K key, V value) {
// Make sure the value is not null
if (value == null) { // value为空就抛出异常
throw new NullPointerException();
}
// Makes sure the key is not already in the hashtable.
Entry<?,?> tab[] = table;
int hash = key.hashCode(); // 计算hash值
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)) { // 如果存在一个hash值和key值都相等的元素就更换value,返回旧的value
V old = entry.value;
entry.value = value;
return old;
}
}
// 添加
addEntry(hash, key, value, index);
return null;
}
// 删除key值为key的key-value
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)) { // 找到删除节点
if (prev != null) { // e为待删节点,prev为e的上一节点
prev.next = e.next; // prev的下一节点指向e的下一节点,e节点丢失
} else {
tab[index] = e.next;
}
modCount++;
count--;
V oldValue = e.value;
e.value = null;
return oldValue;
}
}
return null;
}
// 将map的元素一个一个添加到Hashtable里面
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());
}
// 清空Hashtable,全部设为null
public synchronized void clear() {
Entry<?,?> tab[] = table;
for (int index = tab.length; --index >= 0; )
tab[index] = null;
modCount++;
count = 0;
}
// 克隆一个Hashtable
public synchronized Object clone() {
Hashtable<?,?> t = cloneHashtable();
t.table = new Entry<?,?>[table.length];
for (int i = table.length ; i-- > 0 ; ) {
t.table[i] = (table[i] != null)
? (Entry<?,?>) table[i].clone() : null;
}
t.keySet = null;
t.entrySet = null;
t.values = null;
t.modCount = 0;
return t;
}
/** Calls super.clone() */
final Hashtable<?,?> cloneHashtable() {
try {
return (Hashtable<?,?>)super.clone();
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
}
public synchronized String toString() {
int max = size() - 1;
if (max == -1)
return "{}";
StringBuilder sb = new StringBuilder();
Iterator<Map.Entry<K,V>> it = entrySet().iterator();
sb.append('{');
for (int i = 0; ; i++) {
Map.Entry<K,V> e = it.next();
K key = e.getKey();
V value = e.getValue();
sb.append(key == this ? "(this Map)" : key.toString());
sb.append('=');
sb.append(value == this ? "(this Map)" : value.toString());
if (i == max)
return sb.append('}').toString();
sb.append(", ");
}
}
// 获取Hashtable的枚举类对象
private <T> Enumeration<T> getEnumeration(int type) {
if (count == 0) { // 如果Hashtable为空则返回一个空枚举类对象
return Collections.emptyEnumeration();
} else { // 返回正常的Enumerator对象
return new Enumerator<>(type, false);
}
}
// 获取Hashtable的迭代器
private <T> Iterator<T> getIterator(int type) {
if (count == 0) { // 为空返回空迭代器对象
return Collections.emptyIterator();
} else { // 返回Enumerator对象
return new Enumerator<>(type, true);
}
}
// key的set集合,没有重复元素
private transient volatile Set<K> keySet;
// key-value集合
private transient volatile Set<Map.Entry<K,V>> entrySet;
// value的Collection集合, 允许重复
private transient volatile Collection<V> values;
// 返回一个keySet对象,多线程同步,因为被synchronizedSet封装keySet的所有方法都添加了synchronized关键字
public Set<K> keySet() {
if (keySet == null)
keySet = Collections.synchronizedSet(new KeySet(), this);
return keySet;
}
// key的set集合,没有重复元素
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 Set<Map.Entry<K,V>> entrySet() {
if (entrySet==null)
entrySet = Collections.synchronizedSet(new EntrySet(), this);
return entrySet;
}
// Entry的set集合,没有重复元素
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);
}
// 查找Entry中是否包含o,在table中找到o所对应的entry链表,在判断链中是否存有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;
}
// 删除o,在table中找到o所对应的entry链表,删除链中的o节点
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)) {
if (prev != null)
prev.next = e.next;
else
tab[index] = e.next;
e.value = null; // clear for gc.
modCount++;
count--;
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;
}
// value的Collection集合
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();
}
}
// 重写equals方法如果两个Hashtable的所有key-value都相等就判断他们俩相等
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;
}
// 计算entry的hashCode、
public synchronized int hashCode() {
int h = 0;
// 如果没有key-value或者加载因子小与0,那么hashCode为0
if (count == 0 || loadFactor < 0)
return h; // Returns zero
loadFactor = -loadFactor; // Mark hashCode computation in progress
Entry<?,?>[] tab = table;
for (Entry<?,?> entry : tab) {
while (entry != null) {
h += entry.hashCode();
entry = entry.next;
}
}
loadFactor = -loadFactor; // Mark hashCode computation complete
return h;
}
// 如果key所对应的value为null那么就返回defaultValue否则返回value
@Override
public synchronized V getOrDefault(Object key, V defaultValue) {
V result = get(key);
return (null == result) ? defaultValue : result;
}
}
Hashtable相比HashMap
- 存储结构都是一样的。解决hash冲突的方式也是一样的
- Hashtable默认容量大小为11,HashMap默认大小为16,Hashtable没有强调底层数组必须为2的n次方,而HashMap要求必须为2的幂
- Hashtable要求key和value不能为null,HashMap则是key,value都可以为null。
- Hashtable扩容为容量扩大为原来2倍+1,HashMap为原来的2倍。
- Hashtable计算hash值,直接使用key的hashCode,Hashmap则是重新计算hash值。
- 计算当前元素应该所处数组下标,Hashtable用的%运算,而HashMap用的是与运算。