Hashtable类注释翻译、源码分析

HashMap源码分析 :http://blog.csdn.net/disiwei1012/article/details/73530598
HashSet类注释翻译、fast-fail、源码分析 :http://blog.csdn.net/disiwei1012/article/details/73692452

一、与HashMap的不同之处

HashMapHashtable
线程同步线程不同步
key可以为NULLkey不可以为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();
            }
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值