基於源碼的Java集合框架學習⑩ Hashtable

類 Hashtable

此類實現一個哈希表,該哈希表將鍵映射到相應的值。任何非 null 對象都可以用作鍵或值。

爲了成功地在哈希表中存儲和檢索對象,用作鍵的對象必須實現 hashCode 方法和 equals 方法。
Hashtable 的實例有兩個參數影響其性能:初始容量 和加載因子。容量 是哈希表中桶 的數量,初始容量 就是哈希表創建時的容量。注意,哈希表的狀態爲 open:在發生“哈希衝突”的情況下,單個桶會存儲多個條目,這些條目必須按順序搜索。加載因子 是對哈希表在其容量自動增加之前可以達到多滿的一個尺度。初始容量和加載因子這兩個參數只是對該實現的提示。關於何時以及是否調用 rehash 方法的具體細節則依賴於該實現。

通常,默認加載因子(.75)在時間和空間成本上尋求一種折衷。加載因子過高雖然減少了空間開銷,但同時也增加了查找某個條目的時間(在大多數 Hashtable 操作中,包括 get 和 put 操作,都反映了這一點)。

初始容量主要控制空間消耗與執行 rehash 操作所需要的時間損耗之間的平衡。如果初始容量大於 Hashtable 所包含的最大條目數除以加載因子,則永遠 不會發生 rehash 操作。但是,將初始容量設置太高可能會浪費空間。

如果很多條目要存儲在一個 Hashtable 中,那麼與根據需要執行自動 rehashing 操作來增大表的容量的做法相比,使用足夠大的初始容量創建哈希表或許可以更有效地插入條目。

Hashtable 是同步的。

源碼

Hashtable繼承自Dictionary<K,V>,實現了返回所有key和所有value的枚舉類的方法:

    public synchronized Enumeration<K> keys() {
        return this.<K>getEnumeration(KEYS);
    }
    public synchronized Enumeration<V> elements() {
        return this.<V>getEnumeration(VALUES);
    }

內部的迭代器以及枚舉類都由內部類Enumerator實現:

    private static final int KEYS = 0;
    private static final int VALUES = 1;
    private static final int ENTRIES = 2;

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

與HashMap的比較

Hashtable的鍵和值都不能爲null。
提供的所有方法都是同步的。
無序的。
Hashtable默認的初始大小爲11,之後每次擴充,容量變爲原來的2n+1。HashMap默認的初始化大小爲11,之後每次擴充,容量變爲原來的2倍。
計算hash值的方法不同 。

參考

https://blog.csdn.net/wangxing233/article/details/79452946

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章