package java.util;
import java.io.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.BiFunction;
/**
* Hashtable實現了哈希表,把關鍵字映射到值,不允許空值null
* 作爲關鍵字的對象必須實現hashCode和equals方法,以便從hashtable中存取對象
* 一個Hashtable對象有兩個參數影響其性能:初始容量和裝載因子。容量是哈希表中槽bucket的數目,初始容量只是創建時候的容量
* 哈希表對於哈希衝突是開放式的,一個槽中可能會存儲多個Entry,遍歷的時候只能順序遍歷。
* 裝載因子用來衡量哈希表達到多滿的程度的時候需要重新哈希,具體什麼時候是否需要調用rehash方法還要看具體實現
* 通常默認的裝載因子0.75提供了一個很好的時空取捨
* 初始容量控制了空間浪費與相當耗費時間的rehash操作的必要性之間的取捨。較大的初始容量可以保證不必rehash,但初始容量過大又容易浪費空間。
* 如果有很多Entry需要放進Hashtable,那就創建一個初始容量比較大的哈希表,比自動增長rehash的插入更加高效
* hashtable的使用例子:
* Hashtable<String, Integer> numbers
* = new Hashtable<String, Integer>();
* numbers.put("one", 1);
* numbers.put("two", 2);
* numbers.put("three", 3);}
* 取數據的操作:
* Integer n = numbers.get("two");
* if (n != null) {
* System.out.println("two = " + n);
* }}
* 通過iterator方法返回的迭代器都是fail-fast的:如果迭代器創建之後hashtable發生除了通過迭代器自己的remove函數之外的結構改變,都會拋出ConcurrentModificationException異常
* Hashtable的keys和elements方法返回的枚舉集合enumerator不是fail-fast的
*/
/**
* Hashtable繼承於Dictionary,實現了Map、Cloneable、java.io.Serializable接口
* Hashtable的函數都是同步的,這意味着它是線程安全的。它的key、value都不可以爲null。此外,Hashtable中的映射不是有序的。
* 涉及到結構改變的函數操作都使用synchronized修飾
*/
public class Hashtable<K,V>
extends Dictionary<K,V>
implements Map<K,V>, Cloneable, java.io.Serializable {
/**
* 哈希表中存放數據的地方.
*/
private transient Entry<?,?>[] table;
/**
* 哈希表中所有Entry的數目
*/
private transient int count;
/**
* 重新哈希的閾值(threshold = (int)capacity * loadFactor)
*/
private int threshold;
/**
* hashtable的裝載因子
*/
private float loadFactor;
/**
* Hashtable的結構修改次數。結構修改指的是改變Entry數目或是修改內部結構(如rehash)
* 這個字段用來使Hashtable的集合視圖fail-fast的。
*/
private transient int modCount = 0;
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = 1421746759512286392L;
/**
* 構造函數1:構造一個指定容量和裝載因子的空哈希表
* @param initialCapacity the initial capacity of the hashtable.
* @param loadFactor the load factor of the hashtable.
* @exception IllegalArgumentException if the initial capacity is less
* than zero, or if the load factor is nonpositive.
*/
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);
}
/**
* 構造函數2:構造一個指定容量的空哈希表,默認裝載因子0.75
* @param initialCapacity the initial capacity of the hashtable.
* @exception IllegalArgumentException if the initial capacity is less
* than zero.
*/
public Hashtable(int initialCapacity) {
this(initialCapacity, 0.75f);
}
/**
* 構造函數3:構造一個空哈希表,默認容量11,默認裝載因子0.75
*/
public Hashtable() {
this(11, 0.75f);
}
/**
* 構造函數4:構造一個包含子Map的構造函數,容量爲足夠容納指定Map中元素的2的次冪,默認裝載因子0.75
* @param t the map whose mappings are to be placed in this map.
* @throws NullPointerException if the specified map is null.
*/
public Hashtable(Map<? extends K, ? extends V> t) {
this(Math.max(2*t.size(), 11), 0.75f);
putAll(t);
}
/**
* 返回Hashtable中鍵值對的數目,方法由synchronized修飾,支持同步調用
* @return the number of keys in this hashtable.
*/
public synchronized int size() {
return count;
}
/**
* 測試Hashtable是否爲空,方法由synchronized修飾,支持同步調用
* @return <code>true</code> if this hashtable maps no keys to values;
* <code>false</code> otherwise.
*/
public synchronized boolean isEmpty() {
return count == 0;
}
/**
* 返回Hashtable中所有關鍵字的一個枚舉集合,方法由synchronized修飾,支持同步調用
* @return an enumeration of the keys in this hashtable.
* @see Enumeration
* @see #elements()
* @see #keySet()
* @see Map
*/
public synchronized Enumeration<K> keys() {
return this.<K>getEnumeration(KEYS);
}
/**
* 返回Hashtable中所有值對象的枚舉集合,使用返回對象的getEnumeration方法順序獲取元素
* @return an enumeration of the values in this hashtable.
*/
public synchronized Enumeration<V> elements() {
return this.<V>getEnumeration(VALUES);
}
/**
* 測試Hashtable中是否有關鍵字映射到指定值上。contains(value)比containsKey(key)方法耗時多一些。
* 這個方法與Map接口containsValue方法功能相同
* @param value a value to search for
* @return <code>true</code> if and only if some key maps to the
* <code>value</code> argument in this hashtable as
* determined by the <tt>equals</tt> method;
* <code>false</code> otherwise.
* @exception NullPointerException if the value is <code>null</code>
*/
public synchronized boolean contains(Object value) {
//Hashtable中“鍵值對”的value不能使null,否則拋出異常NullPointerException
if (value == null) {
throw new NullPointerException();
}
//從後向前遍歷table數組中的元素(Entry)
//對於每個Entry(單向鏈表),逐個遍歷,判斷結點的值是否等於value
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;
}
/**
* 與contains功能一樣,本質就是調用了contains函數
* @param value value whose presence in this hashtable is to be tested
* @return <tt>true</tt> if this map maps one or more keys to the
* specified value
* @throws NullPointerException if the value is <code>null</code>
* @since 1.2
*/
public boolean containsValue(Object value) {
return contains(value);
}
/**
* 測試指定Key是否存在
* @param key possible key
* @return <code>true</code> if and only if the specified object
* is a key in this hashtable, as determined by the
* <tt>equals</tt> method; <code>false</code> otherwise.
* @throws NullPointerException if the key is <code>null</code>
*/
public synchronized boolean containsKey(Object key) {
Entry<?,?> tab[] = table;
int hash = key.hashCode();
//關鍵字Key映射的哈希槽下標
int index = (hash & 0x7FFFFFFF) % tab.length;
//遍歷鏈表找到與指定Key相等(equals)的元素
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
* @param key the key whose associated value is to be returned
* @return the value to which the specified key is mapped, or
* {@code null} if this map contains no mapping for the key
* @throws NullPointerException if the specified key is null
* @see #put(Object, Object)
*/
@SuppressWarnings("unchecked")
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;
}
/**
* 分配數組最大容量,一些虛擬機會保存數組的頭字,試圖分配更大的數組會導致OOM(OutOfMemoryError):請求的數組容量超出VM限制
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
* 容量增長時需要內部重新組織Hashtable,以更有效率的訪問
* 當Hashtable中關鍵字數目超出容量與裝載因子之積時,自動調用該方法
*/
@SuppressWarnings("unchecked")
protected void rehash() {
int oldCapacity = table.length; //舊容量
Entry<?,?>[] oldMap = table; //舊Entry數組
// 溢出檢測(超出MAX_ARRAY_SIZE)
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數組
Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];
//修改modCount
modCount++;
//修改新閾值(新閾值也不能超過MAX_ARRAY_SIZE)
threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
table = newMap;
//從後向前遍歷舊錶每一個槽中的鏈表的每一個Entry元素,將其重新哈希到新表中
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插入Index槽中當前鏈表的開頭
e.next = (Entry<K,V>)newMap[index];
newMap[index] = e;
}
}
}
//添加新的Entry元素
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;
}
// 創建新的Entry,並插入Index槽中鏈表的頭部
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>) tab[index];
tab[index] = new Entry<>(hash, key, value, e);
count++;
}
/**
* 將指定的Key映射到指定的value。Key和value都不能爲空null
* @param key the hashtable key
* @param value the value
* @return the previous value of the specified key in this hashtable,
* or <code>null</code> if it did not have one
* @exception NullPointerException if the key or value is
* <code>null</code>
*/
public synchronized V put(K key, V value) {
// 確保value不爲空null
if (value == null) {
throw new NullPointerException();
}
// 確保Key在Hashtable中不存在,若存在,更新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)) {
V old = entry.value;
entry.value = value;
return old;
}
}
//不存在,添加元素
addEntry(hash, key, value, index);
return null;
}
/**
* 刪除關鍵字Key相關的Entry,如果不存在Key,就什麼都不做(只是遍歷一趟鏈表。。)
* @param key the key that needs to be removed
* @return the value to which the key had been mapped in this hashtable,
* or <code>null</code> if the key did not have a mapping
* @throws NullPointerException if the key is <code>null</code>
*/
public synchronized V remove(Object key) {
Entry<?,?> tab[] = table;
int hash = key.hashCode();
//獲取下標Index
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++;
//刪除e
if (prev != null) {
prev.next = e.next;
} else {
tab[index] = e.next;
}
count--;
V oldValue = e.value;
e.value = null;
//返回刪除元素的value值
return oldValue;
}
}
return null;
}
/**
* 將指定Map中的所有映射都拷貝到Hashtable中,已經存在的Key對應的value值會被更新
* @param t mappings to be stored in this map
* @throws NullPointerException if the specified map is null
*/
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,將Hashtable的table數組的值全部設爲null
*/
public synchronized void clear() {
Entry<?,?> tab[] = table;
modCount++;
for (int index = tab.length; --index >= 0; )
tab[index] = null;
count = 0;
}
/**
* 創建一個Hashtable的淺拷貝。Hashtable自身的結構都被拷貝了(拷貝數組,拷貝鏈表),但是其中的關鍵字和值不拷貝(依然引用的同一份Key和value)。
* @return a clone of the hashtable
*/
public synchronized Object clone() {
try {
Hashtable<?,?> t = (Hashtable<?,?>)super.clone();
t.table = new Entry<?,?>[table.length];
for (int i = table.length ; i-- > 0 ; ) {
//依次調用數組裏的鏈表的第一個元素的clone方法,後繼元素都自動複製了,因爲clone中會調用後繼元素的clone
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;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
}
/**
* 返回Hashtable對象的String表達方式,一系列以括號和逗號,空格分隔的Entry,如{key1=value1, key2=value2}
* @return a string representation of this hashtable
*/
public synchronized String toString() {
int max = size() - 1;
//Hashtable中元素爲空
if (max == -1)
return "{}";
//使用StringBuilder,提高字符串拼接效率
StringBuilder sb = new StringBuilder();
//獲得Hashtable的Entry集合
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(", ");
}
}
//獲得指定類型(keys,values,entries)的枚舉集合
private <T> Enumeration<T> getEnumeration(int type) {
if (count == 0) {
return Collections.emptyEnumeration();
} else {
//傳false,新建枚舉器
return new Enumerator<>(type, false);
}
}
//獲得指定類型(keys,values,entries)的迭代器
private <T> Iterator<T> getIterator(int type) {
if (count == 0) {
return Collections.emptyIterator();
} else {
//傳true參數,新建迭代器類型實例
return new Enumerator<>(type, true);
}
}
// 視圖
/**
* 以下每個字段初始化後會包含一個首次請求後的指定視圖,視圖是無狀態的,所以不必創建多個
*/
private transient volatile Set<K> keySet = null;
private transient volatile Set<Map.Entry<K,V>> entrySet = null;
private transient volatile Collection<V> values = null;
/**
* 返回Map的關鍵字視圖Set,Map中的任何修改都會反映在Set中,反過來也是如此。當一個迭代器正在遍歷時,如果Map的結構發生改變,迭代器行爲未定義,
* 如果是使用迭代器的remove函數改變Map結構,不會發生異常
* set<K>支持Iterator.remove,Set.remove,removeAll,retainAll和clear函數
* 不支持add和addAll函數
*/
public Set<K> keySet() {
if (keySet == null)
//返回線程安全的KeySet
keySet = Collections.synchronizedSet(new KeySet(), this);
return keySet;
}
//KeySet類
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();
}
}
/**
* 返回Map中映射的集合Set,Map中的改變會反映在Set中,反之亦是如此。
* 迭代器遍歷Set時,如果Map結構發生變化,迭代器行爲未定義,除了通過迭代器自身的remove操作和setValue操作
* 該Set支持通過Iterator.remove,Set.remove, removeAll, retainAll和clear操作刪除元素
* 不支持add和addAll操作
*/
public Set<Map.Entry<K,V>> entrySet() {
if (entrySet==null)
//返回線程安全的entrySet
entrySet = Collections.synchronizedSet(new EntrySet(), this);
return entrySet;
}
private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
public Iterator<Map.Entry<K,V>> iterator() {
//返回Entry的迭代器
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)
//找到指定Entry
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();
}
}
/**
* 返回Map中所有值的集合視圖,Map中的任何修改都會反映在集合中,反之亦是如此。如果集合遍歷過程中,Map發生結構上的修改,迭代行爲未定義
* 除了通過迭代器自身的remove函數,集合支持元素刪除,通過Iterator.remove,Collection.remove,removeAll,retainAll和clear等行爲操作,
* 但不支持add和addAll操作
*/
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() {
//返回Values迭代器
return getIterator(VALUES);
}
public int size() {
return count;
}
public boolean contains(Object o) {
return containsValue(o);
}
public void clear() {
Hashtable.this.clear();
}
}
// 比較和哈希函數
/**
* 比較指定對象和當前Map,判斷是否相等
* @param o object to be compared for equality with this hashtable
* @return true if the specified Object is equal to this Map
*/
public synchronized boolean equals(Object o) {
//同一個元素,返回true
if (o == this)
return true;
//類型不同,直接否定
if (!(o instanceof Map))
return false;
Map<?,?> t = (Map<?,?>) o;
if (t.size() != size())
return false;
try {
//獲取Entry的迭代器
Iterator<Map.Entry<K,V>> i = entrySet().iterator();
//判斷Map中的每一個元素Entry的鍵值對是不是都在t中存在
while (i.hasNext()) {
Map.Entry<K,V> e = i.next();
K key = e.getKey();
V value = e.getValue();
//如果有不相等或是不存在的,立刻返回false
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;
}
/**
* 返回Map的哈希值,Map中每一個Entry的hashcode相加
* @see Map#hashCode()
*/
public synchronized int hashCode() {
/*
* 這段代碼檢測了由於哈希表自引用引起的遞歸計算,並阻止了棧溢出。
* 這段代碼複用了裝載因子loadFactor字段的功能,作爲一個正在計算的標識位,爲了節省空間。
* 裝載因子爲負說明正在計算hashcode
*/
int h = 0;
if (count == 0 || loadFactor < 0)
return h; // 返回0
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;
}
@Override
public synchronized V getOrDefault(Object key, V defaultValue) {
V result = get(key);
return (null == result) ? defaultValue : result;
}
@SuppressWarnings("unchecked")
@Override
public synchronized void forEach(BiConsumer<? super K, ? super V> action) {
Objects.requireNonNull(action); // explicit check required in case
// table is empty.
final int expectedModCount = modCount;
Entry<?, ?>[] tab = table;
for (Entry<?, ?> entry : tab) {
while (entry != null) {
action.accept((K)entry.key, (V)entry.value);
entry = entry.next;
if (expectedModCount != modCount) {
throw new ConcurrentModificationException();
}
}
}
}
@SuppressWarnings("unchecked")
@Override
public synchronized void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
Objects.requireNonNull(function); // explicit check required in case
// table is empty.
final int expectedModCount = modCount;
Entry<K, V>[] tab = (Entry<K, V>[])table;
for (Entry<K, V> entry : tab) {
while (entry != null) {
entry.value = Objects.requireNonNull(
function.apply(entry.key, entry.value));
entry = entry.next;
if (expectedModCount != modCount) {
throw new ConcurrentModificationException();
}
}
}
}
//存在Key就更新,不存在就添加
@Override
public synchronized V putIfAbsent(K key, V value) {
Objects.requireNonNull(value); //檢測value非空
// 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;
if (old == null) {
entry.value = value;
}
return old;
}
}
addEntry(hash, key, value, index);
return null;
}
//刪除指定Key-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)) {
modCount++;
if (prev != null) {
prev.next = e.next;
} else {
tab[index] = e.next;
}
count--;
e.value = null;
return true;
}
}
return false;
}
//替換舊值爲新值,如果key對應的值不等於舊值(equals),就不替換
@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)) {
if (e.value.equals(oldValue)) {
e.value = newValue;
return true;
} else {
return false;
}
}
}
return false;
}
//替換值,如果不存在key,返回null
@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) {
if ((e.hash == hash) && e.key.equals(key)) {
V oldValue = e.value;
e.value = value;
return oldValue;
}
}
return null;
}
//如果不存在Key,就添加鍵值對key-value,value通過mappingFunction計算得到
@Override
public synchronized V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
Objects.requireNonNull(mappingFunction);
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)) {
// Hashtable not accept null value
return e.value;
}
}
V newValue = mappingFunction.apply(key);
if (newValue != null) {
addEntry(hash, key, newValue, index);
}
return newValue;
}
//如果存在就替換Key的value值,value通過mappingFunction計算得到,如果計算得到的value爲null,就刪除Key對應的Entry
@Override
public synchronized V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
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)) {
V newValue = remappingFunction.apply(key, e.value);
//Hashtable不允許鍵值爲null,刪除Key對應的Entry
if (newValue == null) {
modCount++;
if (prev != null) {
prev.next = e.next;
} else {
tab[index] = e.next;
}
count--;
} else {
//不爲空,替換爲新值
e.value = newValue;
}
return newValue;
}
}
return null;
}
@Override
public synchronized V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
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 && Objects.equals(e.key, key)) {
V newValue = remappingFunction.apply(key, e.value);
if (newValue == null) {
modCount++;
if (prev != null) {
prev.next = e.next;
} else {
tab[index] = e.next;
}
count--;
} else {
e.value = newValue;
}
return newValue;
}
}
V newValue = remappingFunction.apply(key, null);
if (newValue != null) {
addEntry(hash, key, newValue, index);
}
return newValue;
}
@Override
public synchronized V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
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)) {
V newValue = remappingFunction.apply(e.value, value);
if (newValue == null) {
modCount++;
if (prev != null) {
prev.next = e.next;
} else {
tab[index] = e.next;
}
count--;
} else {
e.value = newValue;
}
return newValue;
}
}
if (value != null) {
addEntry(hash, key, value, index);
}
return value;
}
/**
* 將Hashtable的狀態保存進流中
* @serialData The <i>capacity</i> of the Hashtable (the length of the
* bucket array) is emitted (int), followed by the
* <i>size</i> of the Hashtable (the number of key-value
* mappings), followed by the key (Object) and value (Object)
* for each key-value mapping represented by the Hashtable
* The key-value mappings are emitted in no particular order.
*/
private void writeObject(java.io.ObjectOutputStream s)
throws IOException {
Entry<Object, Object> entryStack = null;
synchronized (this) {
// Write out the length, threshold, loadfactor
s.defaultWriteObject();
// Write out length, count of elements
s.writeInt(table.length);
s.writeInt(count);
// Stack copies of the entries in the table
for (int index = 0; index < table.length; index++) {
Entry<?,?> entry = table[index];
while (entry != null) {
entryStack =
new Entry<>(0, entry.key, entry.value, entryStack);
entry = entry.next;
}
}
}
// Write out the key/value objects from the stacked entries
while (entryStack != null) {
s.writeObject(entryStack.key);
s.writeObject(entryStack.value);
entryStack = entryStack.next;
}
}
/**
* 從流中重建Hashtable(反序列化)
*/
private void readObject(java.io.ObjectInputStream s)
throws IOException, ClassNotFoundException
{
// Read in the length, threshold, and loadfactor
s.defaultReadObject();
// Read the original length of the array and number of elements
int origlength = s.readInt();
int elements = s.readInt();
// Compute new size with a bit of room 5% to grow but
// no larger than the original size. Make the length
// odd if it's large enough, this helps distribute the entries.
// Guard against the length ending up zero, that's not valid.
int length = (int)(elements * loadFactor) + (elements / 20) + 3;
if (length > elements && (length & 1) == 0)
length--;
if (origlength > 0 && length > origlength)
length = origlength;
table = new Entry<?,?>[length];
threshold = (int)Math.min(length * loadFactor, MAX_ARRAY_SIZE + 1);
count = 0;
// Read the number of elements and then all the key/value objects
for (; elements > 0; elements--) {
@SuppressWarnings("unchecked")
K key = (K)s.readObject();
@SuppressWarnings("unchecked")
V value = (V)s.readObject();
// synch could be eliminated for performance
reconstitutionPut(table, key, value);
}
}
/**
* readObject使用的put方法(重建put),因爲put方法支持重寫,並且子類尚未初始化的時候不能調用put方法,所以就提供了reconstitutionPut
* 它和常規put方法有幾點不同,不檢測rehash,因爲初始元素數目已知。modCount不會自增,因爲我們是在創建一個新的實例。
* 不需要返回值
*/
private void reconstitutionPut(Entry<?,?>[] tab, K key, V value)
throws StreamCorruptedException
{
if (value == null) {
throw new java.io.StreamCorruptedException();
}
// 確保Key不在Hashtable中
// 反序列化過程中不應該 會發生的情況
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
//反序列化過程中如果出現Key值重複,拋出異常StreamCorruptedException
if ((e.hash == hash) && e.key.equals(key)) {
throw new java.io.StreamCorruptedException();
}
}
// 創建新的Entry.
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)tab[index];
tab[index] = new Entry<>(hash, key, value, e);
count++;
}
/**
* Hashtable使用單向鏈表Entry解決哈希衝突
*/
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;
}
//返回一個自身的複製對象,淺拷貝,因爲還是引用的當前key和value對象,沒有新建key和value對象
@SuppressWarnings("unchecked")
protected Object clone() {
return new Entry<>(hash, key, value,
(next==null ? null : (Entry<K,V>) next.clone()));
}
// Map.Entry 操作
public K getKey() {
return key;
}
public V getValue() {
return value;
}
public V setValue(V value) {
//Hashtable不允許空null值
if (value == null)
throw new NullPointerException();
V oldValue = this.value;
this.value = value;
//返回原值
return oldValue;
}
//重寫equals方法
public boolean equals(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
//類型相同且鍵值(key-value)也相同(equals返回true)
return (key==null ? e.getKey()==null : key.equals(e.getKey())) &&
(value==null ? e.getValue()==null : value.equals(e.getValue()));
}
public int hashCode() {
//hash值只與關鍵字key有關,hashCode需要與值value的hashCode異或
return hash ^ Objects.hashCode(value);
}
public String toString() {
return key.toString()+"="+value.toString();
}
}
// Enumerations/Iterations的類型
private static final int KEYS = 0;
private static final int VALUES = 1;
private static final int ENTRIES = 2;
/**
* Hashtable的枚舉類。實現了迭代器和枚舉接口,但是去掉迭代器方法也能單獨創建實例
* 這對於避免只通過傳遞枚舉類型來提升容量的意外情況很重要
*/
private class Enumerator<T> implements Enumeration<T>, Iterator<T> {
Entry<?,?>[] table = Hashtable.this.table; //由Hashtable的table數組支持
int index = table.length; //table數組的長度
Entry<?,?> entry = null; //下一個返回元素
Entry<?,?> lastReturned = null; //上一次返回元素
int type; //類型:KEYS,Values,Entries
/**
* 表明當前枚舉是作爲一個迭代器還是一個枚舉類型(true表示迭代器)
*/
boolean iterator;
/**
* 迭代器認爲Hashtable應該擁有的modCount值。如果期望的不一致,迭代器就檢測到併發修改了
*/
protected int expectedModCount = modCount;
/**
* 構造函數:構造一個類型爲type的迭代器或枚舉集合(iterator爲true表示迭代器)
* @param type
* @param iterator
*/
Enumerator(int type, boolean iterator) {
this.type = type;
this.iterator = iterator;
}
//是否還有更多元素
public boolean hasMoreElements() {
Entry<?,?> e = entry;
int i = index;
Entry<?,?>[] t = table;
/* 使用本地變量可以使迭代循環的更快*/
//上一個返回元素爲空,表明從頭開始返回
while (e == null && i > 0) {
//table數組從後向前遍歷,找到第一個非空元素
e = t[--i];
}
entry = e;
index = i;
return e != null;
}
//返回下一個元素
@SuppressWarnings("unchecked")
public T nextElement() {
Entry<?,?> et = entry;
int i = index;
Entry<?,?>[] t = table;
/* 使用本地變量可以使循環迭代得更快 */
//上一個返回元素爲空,表明開始返回第一個元素
while (et == null && i > 0) {
//table數組從後向前遍歷,找到第一個非空元素
et = t[--i];
}
entry = et;
index = i; //更新Index爲當前返回的最大i
if (et != null) {
Entry<?,?> e = lastReturned = entry; //更新上一個返回元素爲當前即將返回的元素
entry = e.next; //更新下一個返回元素爲e.next
//類型爲keys則返回Key,爲value則返回value,否則返回Entry
return type == KEYS ? (T)e.key : (type == VALUES ? (T)e.value : (T)e);
}
//拋出找不到元素異常
throw new NoSuchElementException("Hashtable Enumerator");
}
// 迭代器方法
public boolean hasNext() {
return hasMoreElements();
}
//返回下一個元素
public T next() {
//首先檢測併發修改異常
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
//調用nextElement方法
return nextElement();
}
//刪除函數,刪除的是上一個返回元素lastReturned
public void remove() {
//只有迭代器類型支持該函數 ,否則拋出不支持該操作異常UnsupportedOperationException()
if (!iterator)
throw new UnsupportedOperationException();
//如果上一個返回元素爲空,拋出非法狀態異常IllegalStateException
if (lastReturned == null)
throw new IllegalStateException("Hashtable Enumerator");
//檢測併發修改異常ConcurrentModificationException
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
//刪除時,需要鎖住全表
synchronized(Hashtable.this) {
Entry<?,?>[] tab = Hashtable.this.table;
//上一個返回元素的哈希值最高位之外的所有位模table的長度
int index = (lastReturned.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 == lastReturned) {
modCount++;
expectedModCount++;
//刪除上一個元素
if (prev == null)
tab[index] = e.next;
else
prev.next = e.next;
count--;
lastReturned = null;
return;
}
}
throw new ConcurrentModificationException();
}
}
}
}
從源碼理解Hashtable.java
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.