Hashtable類註釋翻譯、源碼分析

HashMap源碼分析 :http://blog.csdn.net/disiwei1012/article/details/73530598
HashSet類註釋翻譯、fast-fail、源碼分析 :http://blog.csdn.net/disiwei1012/article/details/73692452

一、與HashMap的不同之處

HashMap Hashtable
線程同步 線程不同步
key可以爲NULL key不可以爲NULL
使用fail-fast迭代器 enumerator迭代器
繼承AbstractMap 繼承Dictionary

我們在閱讀源碼的過程中可以着重分析HashTable的四個特點。

二、類註釋翻譯

This class implements a hash table, which maps keys to values. Any
non -<code>null </code> object can be used as a key or as a value. <p>

HashTable類底層基於hash表,用來存儲鍵值對。除了NULL,任何對象都可作爲HashTable的鍵或者值。以下兩種方式都會拋出空指針異常:

Hashtable<String,String> h = new Hashtable<String,String>();
h.put( "123" , null );
h.put( null , "123" );
To successfully store and retrieve objects from a hashtable, the
objects used as keys must implement the <code> hashCode</code>
method and the <code> equals</code> method. <p>

爲了能夠成功的存儲、檢索對象,作爲鍵的那個對象必須要實現hashCode和equals方法。

An instance of <code> Hashtable</code> has two parameters that affect its
performance: <i>initial capacity </i> and <i> load factor</i> .  The
 <i>capacity </i> is the number of <i> buckets </i> in the hash table, and the
 <i>initial capacity </i> is simply the capacity at the time the hash table
is created.  Note that the hash table is <i> open</i> : in the case of a "hash
collision", a single bucket stores multiple entries, which must be searched
sequentially.  The <i> load factor</i> is a measure of how full the hash
table is allowed to get before its capacity is automatically increased.
The initial capacity and load factor parameters are merely hints to
the implementation.  The exact details as to when and whether the rehash
method is invoked are implementation - dependent.<p>

有兩個參數會影響Hashtable的效率。一個是initial capacity(初始容量);另外一個是load factor(加載因子)。
容量就是hash表中桶的數量。hash表被創建時的容量稱爲initial capacity。
注意,HashTable運用拉鍊法(open hashing)處理hash衝突(hash collision),所謂拉鍊法就是當兩個key的hash值相同時,放在同一個桶中。與之對應的 Closed Hashing稱爲開放地址法,即是因爲哈希衝突後,並不會在本身之外開拓新的空間,而是繼續順延下去某個位置來存放,所以是一個密閉的空間,所以叫“Closed”。
加載因子是集合是否需要擴容的重要參數。初始化容量和加載因子僅僅是實現的提示,關於何時和是否執行rehash方法(用來擴展集合容量)是依賴於具體實現的。

What does it mean by “the hash table is open” in Java?
https://stackoverflow.com/questions/1288692/what-does-it-mean-by-the-hash-table-is-open-in-java

Generally, the default load factor (.75) offers a good tradeoff between
time and space costs.  Higher values decrease the space overhead but
increase the time cost to look up an entry (which is reflected in most
<tt>Hashtable</tt> operations, including <tt>get</tt> and <tt>put</tt>).<p>

總的來講,默認加載因子(0.75)是時間和空間還不錯的平衡。更高的加載因子可以更好的利用空間,但是對於元素操作的效率會變低。

The initial capacity controls a tradeoff between wasted space and the
need for <code>rehash</code> operations, which are time-consuming.
No <code>rehash</code> operations will <i>ever</i> occur if the initial
capacity is greater than the maximum number of entries the
<tt>Hashtable</tt> will contain divided by its load factor.  However,
setting the initial capacity too high can waste space.<p>

初始容量對空間浪費和好時的rehash操作進行了折中。如何hash表元素數量大於初始容量乘加載因子,則需要執行rehash操作。
然而,初始容量值太高也會導致浪費空間。

If many entries are to be made into a <code>Hashtable</code>,
creating it with a sufficiently large capacity may allow the
entries to be inserted more efficiently than letting it perform
automatic rehashing as needed to grow the table. <p>

如果Hashtable中需要存放大量的元素,較高的hash容量會比因空間不夠而自動進行的rehash操作更加高效。

* This example creates a hashtable of numbers. It uses the names of
 * the numbers as keys:
 * <pre>   {@code
 *   Hashtable<String, Integer> numbers
 *     = new Hashtable<String, Integer>();
 *   numbers.put("one", 1);
 *   numbers.put("two", 2);
 *   numbers.put("three", 3);}</pre>
 *
 * <p>To retrieve a number, use the following code:
 * <pre>   {@code
 *   Integer n = numbers.get("two");
 *   if (n != null) {
 *     System.out.println("two = " + n);
 *   }}</pre>

 * <p>The iterators returned by the <tt>iterator</tt> method of the collections
 * returned by all of this class's "collection view methods" are
 * <em>fail-fast</em>: if the Hashtable is structurally modified at any time
 * after the iterator is created, in any way except through the iterator's own
 * <tt>remove</tt> method, the iterator will throw a {@link
 * ConcurrentModificationException}.  Thus, in the face of concurrent
 * modification, the iterator fails quickly and cleanly, rather than risking
 * arbitrary, non-deterministic behavior at an undetermined time in the future.
 * The Enumerations returned by Hashtable's keys and elements methods are
 * <em>not</em> fail-fast.

通過集合iterator方法或者類的集合遍歷方法返回的迭代器都具有fail-fast特性。所謂fail-fast即:如果已經創建好了迭代器,再對集合進行結構性修改(除了迭代器的remove方法),則會拋出ConcurrentModificationException。
在面對併發修改,fail-fast快速拋出異常,而不是浪費時間和效率,等待錯誤的發生。
而Enumerations迭代器則不具有fail-fast特性。

 * 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}.

和新的集合類不同,Hashtable是同步的。如果不需要線程安全,推薦使用HashMap。如果需要高併發線程安全,則推薦使用ConcurrentHashMap。

三、fail-fast迭代器與 Enumeration迭代器

前者在功能上可以完全替代後者。後者目前還保留在Java標準庫裏純粹是爲了兼容老API(例如Hashtable、Vector、Stack等老的collection類型)。
前者相比後者有以下區別:
① 前者的方法名比後者簡明扼要
② 前者添加了一個可選的remove()方法(使用這個方法不會導致ConcurrentModificationException 異常)
③ 前者是“fail-fast”的——如果它在遍歷過程中,底下的容器發生了結構變化(例如add或者remove了元素),則它會拋出ConcurrentModificationException;後者沒有這種檢查機制

public interface Iterator <E> {

    boolean hasNext();

    E next();

    void remove();
}

public interface Enumeration <E> {

    boolean hasMoreElements();

    E nextElement();
}

在1.7中,Hashtable使用實現了Enumeration和Iterator接口的內部類Enumerator,Enumerator同時具有Enumeration迭代器和fail-fast迭代器的特點。
我們來看內部類Enumerator:

    private class Enumerator<T> implements Enumeration<T>, Iterator<T> {
        Entry[] table = Hashtable.this.table;
        int index = table.length;
        Entry<K,V> entry = null;
        Entry<K,V> lastReturned = null;
        int type;

        boolean iterator;
        protected int expectedModCount = modCount;

        Enumerator(int type, boolean iterator) {
            this.type = type;
            this.iterator = iterator;
        }

        public boolean hasMoreElements() {
            Entry<K,V> e = entry;
            int i = index;
            Entry[] t = table;
            /* Use locals for faster loop iteration */
            while (e == null && i > 0) {
                e = t[--i];
            }
            entry = e;
            index = i;
            return e != null;
        }

        public T nextElement() {
            Entry<K,V> et = entry;
            int i = index;
            Entry[] t = table;
            /* Use locals for faster loop iteration */
            while (et == null && i > 0) {
                et = t[--i];
            }
            entry = et;
            index = i;
            if (et != null) {
                Entry<K,V> e = lastReturned = entry;
                entry = e.next;
                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();
            return nextElement();
        }

        public void remove() {
            if (!iterator)
                throw new UnsupportedOperationException();
            if (lastReturned == null)
                throw new IllegalStateException("Hashtable Enumerator");
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();

            synchronized(Hashtable.this) {
                Entry[] tab = Hashtable.this.table;
                int index = (lastReturned.hash & 0x7FFFFFFF) % tab.length;

                for (Entry<K,V> e = tab[index], 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();
            }
        }
    }

四、源碼

package java.util;
import java.io.*;

public class Hashtable<K,V>
    extends Dictionary<K,V>
    implements Map<K,V>, Cloneable, java.io.Serializable {

    /**
     * hash數組,用來存儲數據(鍵值對),每一個Entry相當於一個單向鏈表
     * 另外需要注意,數組table,大多數情況下不會全部用來存放元素,會空閒幾個。
     * 具體會使用多少,等於 loadFactor * capacity(也就是threshold)
     */
    private transient Entry<K,V>[] table;

    /**
     * hash表中元素的數量
     */
    private transient int count;

    /**
     * 當hash表中元素的數量(count)超過threshold,則需要擴容(threshold=capacity*loadFactor)
     */
    private int threshold;

    /**
     * 加載因子
     */
    private float loadFactor;

    /**
     * hash表被修改次數
     */
    private transient int modCount = 0;

    private static final long serialVersionUID = 1421746759512286392L;

    static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = Integer.MAX_VALUE;

    private static class Holder {

        /**
         * Table capacity above which to switch to use alternative hashing.
         */
        static final int ALTERNATIVE_HASHING_THRESHOLD;

        static {
            String altThreshold = java.security.AccessController.doPrivileged(
                new sun.security.action.GetPropertyAction(
                    "jdk.map.althashing.threshold"));

            int threshold;
            try {
                threshold = (null != altThreshold)
                        ? Integer.parseInt(altThreshold)
                        : ALTERNATIVE_HASHING_THRESHOLD_DEFAULT;

                // disable alternative hashing if -1
                if (threshold == -1) {
                    threshold = Integer.MAX_VALUE;
                }

                if (threshold < 0) {
                    throw new IllegalArgumentException("value must be positive integer.");
                }
            } catch(IllegalArgumentException failed) {
                throw new Error("Illegal value for 'jdk.map.althashing.threshold'", failed);
            }

            ALTERNATIVE_HASHING_THRESHOLD = threshold;
        }
    }

    transient boolean useAltHashing;

    private static final sun.misc.Unsafe UNSAFE;

    private static final long HASHSEED_OFFSET;

     static {
        try {
            UNSAFE = sun.misc.Unsafe.getUnsafe();
            HASHSEED_OFFSET = UNSAFE.objectFieldOffset(
                Hashtable.class.getDeclaredField("hashSeed"));
        } catch (NoSuchFieldException | SecurityException e) {
            throw new Error("Failed to record hashSeed offset", e);
        }
     }

    transient final int hashSeed = sun.misc.Hashing.randomHashSeed(this);

    //計算hashCode
    private int hash(Object k) {
        if (useAltHashing) {
            if (k.getClass() == String.class) {
                return sun.misc.Hashing.stringHash32((String) k);
            } else {
                int h = hashSeed ^ k.hashCode();

                // This function ensures that hashCodes that differ only by
                // constant multiples at each bit position have a bounded
                // number of collisions (approximately 8 at default load factor).
                h ^= (h >>> 20) ^ (h >>> 12);
                return h ^ (h >>> 7) ^ (h >>> 4);
             }
        } else  {
            return k.hashCode();
        }
    }

    /**
     * 指定容量大小和加載因子的構造方法
     */
    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;
        //創建hash數組
        table = new Entry[initialCapacity];
        threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
        useAltHashing = sun.misc.VM.isBooted() &&
                (initialCapacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
    }

    /**
     * 指定容量大小和默認加載因子(0.75)的構造方法
     *
     */
    public Hashtable(int initialCapacity) {
        this(initialCapacity, 0.75f);
    }

    /**
     * 指定默認初始容量(11)和默認加載因子(0.75)的構造方法
     * 
     */
    public Hashtable() {
        this(11, 0.75f);
    }

    /**
     * 帶有Map參數的構造函數
     * 
     */
    public Hashtable(Map<? extends K, ? extends V> t) {
        this(Math.max(2*t.size(), 11), 0.75f);
        //將map中的所有元素加入到Hashtable中
        putAll(t);
    }

    /**
     * 返回元素的數量
     */
    public synchronized int size() {
        return count;
    }

    /**
     * 判斷元素數量是否爲0
     */
    public synchronized boolean isEmpty() {
        return count == 0;
    }

    /**
     * 返回一個key的enumeration迭代器
     */
    public synchronized Enumeration<K> keys() {
        return this.<K>getEnumeration(KEYS);
    }

    /**
     * 返回一個value的enumeration迭代器
     */
    public synchronized Enumeration<V> elements() {
        return this.<V>getEnumeration(VALUES);
    }

    /**
     * 判斷Hashtable中是否包含值爲value的元素,該方法效率低於containsKey
     */
    public synchronized boolean contains(Object value) {
        if (value == null) {//Object爲null,則拋出空指針
            throw new NullPointerException();
        }

        Entry tab[] = table;
        for (int i = tab.length ; i-- > 0 ;) {
            for (Entry<K,V> 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);
    }

    /**
     * 判斷Hashtable中是否包含鍵爲key的元素
     * 和此方法containsValue的區別在於:containsValue既要遍歷數組,又要遍歷鏈表
     * containsKey 先找到數組位置,然後遍歷該位置的單向鏈表就可以了
     */
    public synchronized boolean containsKey(Object key) {
        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)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 返回key對應的value,沒有的話返回null
     */
    public synchronized V get(Object key) {
        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)) {
                return e.value;
            }
        }
        return null;
    }

    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    /**
     * 當元素數量count超過threshold,則會自動調用該方法進行擴容。
     * 將長度變爲原來的2倍+1
     */
    protected void rehash() {
        //舊數組大小oldCapacity
        int oldCapacity = table.length;
        Entry<K,V>[] 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;
        }
        //創建新數組
        Entry<K,V>[] newMap = new Entry[newCapacity];
        //修改次數+1
        modCount++;
        threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
        boolean currentAltHashing = useAltHashing;
        useAltHashing = sun.misc.VM.isBooted() &&
                (newCapacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
        boolean rehash = currentAltHashing ^ useAltHashing;

        table = newMap;
        //將舊數組中的數據依次添加到新table數組中
        for (int i = oldCapacity ; i-- > 0 ;) {
            for (Entry<K,V> old = oldMap[i] ; old != null ; ) {
                Entry<K,V> e = old;
                old = old.next;

                if (rehash) {
                    e.hash = hash(e.key);
                }
                int index = (e.hash & 0x7FFFFFFF) % newCapacity;
                e.next = newMap[index];
                newMap[index] = e;
            }
        }
    }

    /**
     * 將“key-value”鍵值對添加到Hashtable中,
     * key和value都不能爲null
     */
    public synchronized V put(K key, V value) {
        //HashTable中不能插入value爲null的元素 
        if (value == null) {
            throw new NullPointerException();
        }

        // 若HashTable中已存在鍵爲key的鍵值對,則用新的value替換舊的value
        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;
            }
        }
        //更改修改次數+1
        modCount++;
        if (count >= threshold) {
            // Rehash the table if the threshold is exceeded
            rehash();

            tab = table;
            hash = hash(key);
            index = (hash & 0x7FFFFFFF) % tab.length;
        }

        //將Hashtable中index位置的Entry(鏈表)保存到e中,將鍵值對插進entry鏈表中
        Entry<K,V> e = tab[index];
        tab[index] = new Entry<>(hash, key, value, e);
        //元素數量+1 
        count++;
        return null;
    }

    /**
     * 刪除Hashtable中鍵爲key的元素,如果不存在此key,那麼什麼都不做
     */
    public synchronized V remove(Object key) {
        Entry tab[] = table;
        int hash = hash(key);
        int index = (hash & 0x7FFFFFFF) % tab.length;
        for (Entry<K,V> e = tab[index], 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;
    }

    /**
     * 遍歷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,將HashTable的table數組的值全部設置爲null
     */
    public synchronized void clear() {
        Entry tab[] = table;
        modCount++;
        for (int index = tab.length; --index >= 0; )
            tab[index] = null;
        count = 0;
    }

    /**
     * 克隆一個Hashtable,並以Object的形式返回。
     */
    public synchronized Object clone() {
        try {
            Hashtable<K,V> t = (Hashtable<K,V>) super.clone();
            t.table = new Entry[table.length];
            for (int i = table.length ; i-- > 0 ; ) {
                t.table[i] = (table[i] != null)
                    ? (Entry<K,V>) 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();
        }
    }

    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(", ");
        }
    }

    //返回Enumerator迭代器
    private <T> Enumeration<T> getEnumeration(int type) {
        if (count == 0) {
            return Collections.emptyEnumeration();
        } else {
            return new Enumerator<>(type, false);
        }
    }

    //返回Iterator迭代器
    private <T> Iterator<T> getIterator(int type) {
        if (count == 0) {
            return Collections.emptyIterator();
        } else {
            return new Enumerator<>(type, true);
        }
    }


    public Set<K> keySet() {
        if (keySet == null)
            keySet = Collections.synchronizedSet(new KeySet(), this);
        return keySet;
    }

    //Hashtable的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();
        }
    }

    public Set<Map.Entry<K,V>> entrySet() {
        if (entrySet==null)
            entrySet = Collections.synchronizedSet(new EntrySet(), this);
        return entrySet;
    }

    // Hashtable的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);
        }

        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 = hash(key);
            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;
        }

        public boolean remove(Object o) {
            if (!(o instanceof Map.Entry))
                return false;
            Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
            K key = entry.getKey();
            Entry[] tab = table;
            int hash = hash(key);
            int index = (hash & 0x7FFFFFFF) % tab.length;

            for (Entry<K,V> e = tab[index], 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();
        }
    }

    //返回value集合,線程安全
    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() {
            return getIterator(VALUES);
        }
        public int size() {
            return count;
        }
        public boolean contains(Object o) {
            return containsValue(o);
        }
        public void clear() {
            Hashtable.this.clear();
        }
    }

    public synchronized boolean equals(Object o) {
        if (o == this)
            return true;

        if (!(o instanceof Map))
            return false;
        Map<K,V> t = (Map<K,V>) o;
        if (t.size() != size())
            return false;

        try {
            Iterator<Map.Entry<K,V>> i = entrySet().iterator();
            while (i.hasNext()) {
                Map.Entry<K,V> e = i.next();
                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;  // Returns zero

        loadFactor = -loadFactor;  // Mark hashCode computation in progress
        Entry[] tab = table;
        for (Entry<K,V> entry : tab)
            while (entry != null) {
                h += entry.hashCode();
                entry = entry.next;
            }
        loadFactor = -loadFactor;  // Mark hashCode computation complete

        return h;
    }



    /**
     * hashtable單向鏈表實現
     */
    private static class Entry<K,V> implements Map.Entry<K,V> {
        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;
        }

        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.equals(e.getKey()) && value.equals(e.getValue());
        }

        public int hashCode() {
            return hash ^ value.hashCode();
        }

        public String toString() {
            return key.toString()+"="+value.toString();
        }
    }


    //Enumeration迭代器
    private class Enumerator<T> implements Enumeration<T>, Iterator<T> {
        Entry[] table = Hashtable.this.table;
        int index = table.length;
        Entry<K,V> entry = null;
        Entry<K,V> lastReturned = null;
        int type;

        /**
         * Indicates whether this Enumerator is serving as an Iterator
         * or an Enumeration.  (true -> Iterator).
         */
        boolean iterator;

        /**
         * The modCount value that the iterator believes that the backing
         * Hashtable should have.  If this expectation is violated, the iterator
         * has detected concurrent modification.
         */
        protected int expectedModCount = modCount;

        Enumerator(int type, boolean iterator) {
            this.type = type;
            this.iterator = iterator;
        }

        public boolean hasMoreElements() {
            Entry<K,V> e = entry;
            int i = index;
            Entry[] t = table;
            /* Use locals for faster loop iteration */
            while (e == null && i > 0) {
                e = t[--i];
            }
            entry = e;
            index = i;
            return e != null;
        }

        public T nextElement() {
            Entry<K,V> et = entry;
            int i = index;
            Entry[] t = table;
            /* Use locals for faster loop iteration */
            while (et == null && i > 0) {
                et = t[--i];
            }
            entry = et;
            index = i;
            if (et != null) {
                Entry<K,V> e = lastReturned = entry;
                entry = e.next;
                return type == KEYS ? (T)e.key : (type == VALUES ? (T)e.value : (T)e);
            }
            throw new NoSuchElementException("Hashtable Enumerator");
        }

        // Iterator methods
        public boolean hasNext() {
            return hasMoreElements();
        }

        public T next() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            return nextElement();
        }

        public void remove() {
            if (!iterator)
                throw new UnsupportedOperationException();
            if (lastReturned == null)
                throw new IllegalStateException("Hashtable Enumerator");
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();

            synchronized(Hashtable.this) {
                Entry[] tab = Hashtable.this.table;
                int index = (lastReturned.hash & 0x7FFFFFFF) % tab.length;

                for (Entry<K,V> e = tab[index], 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();
            }
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章