源碼之HashTable

來源:互聯網
上載者:User

標籤:check   n+1   表示   hash函數   碰撞   安全   bucket   void   初始   

建構函式
   public Hashtable(int initialCapacity, float loadFactor) {        if (initialCapacity < 0)            throw new IllegalArgumentException("Illegal Capacity: "+                                               initialCapacity);        if (loadFactor <= 0 || Float.isNaN(loadFactor))            throw new IllegalArgumentException("Illegal Load: "+loadFactor);        if (initialCapacity==0)            initialCapacity = 1;        this.loadFactor = loadFactor;        table = new Entry<?,?>[initialCapacity];        threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);    }    public Hashtable(int initialCapacity) {        this(initialCapacity, 0.75f);    }    public Hashtable() {        this(11, 0.75f);    }        public Hashtable(Map<? extends K, ? extends V> t) {        this(Math.max(2*t.size(), 11), 0.75f);        putAll(t);    }

分析:
Hashtable(int initialCapacity, float loadFactor)建構函式預設容量是11,載入因子(負載因子)0.75,如果第四個建構函式,那麼就取2*size與11更大的那個作為初始容量。我們知道HashMap的容量一定是2整數次冪,用的初始容量為16,HashTable為啥用11為預設初始容量?我們先帶著這個問題繼續往下看。

Put方法
    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());    }        public synchronized V put(K key, V value) {        // Make sure the value is not null        if (value == null) {            throw new NullPointerException();        }        // 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;                entry.value = value;                return old;            }        }        addEntry(hash, key, value, index);        return null;    }        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;        }        // Creates the new entry.        @SuppressWarnings("unchecked")        Entry<K,V> e = (Entry<K,V>) tab[index];        tab[index] = new Entry<>(hash, key, value, e);        count++;    }        protected void rehash() {        int oldCapacity = table.length;        Entry<?,?>[] oldMap = table;        // overflow-conscious code        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<?,?>[] newMap = new Entry<?,?>[newCapacity];        modCount++;        threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);        table = newMap;        for (int i = oldCapacity ; i-- > 0 ;) {            for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) {                Entry<K,V> e = old;                old = old.next;                int index = (e.hash & 0x7FFFFFFF) % newCapacity;                e.next = (Entry<K,V>)newMap[index];                newMap[index] = e;            }        }    }

分析:
int index = (hash & 0x7FFFFFFF) % tab.length;這句話是做什麼用的呢?(hash & 0x7FFFFFFF) 的&位元運算是為了確保是一個正整數,而hash是一個有符號數。如果hash值相同,那麼再去比較key是不是相等,如果相等那麼替換old值,並返回old值。如果沒有找到相同的key,那麼說明不同的key發生了碰撞,那麼就利用鏈地址法解決這個問題,把新元素串連到該index後面的尾部。在串連到index後面之前,是否進行擴容的判斷,如果達到臨界值,那麼進行擴容,一旦擴容之後需要重新構建hash表,int newCapacity = (oldCapacity << 1) + 1;這句表示擴容後的大小(2n+1),然後把原來的hashtable值拷貝到新hashtable中,從這裡我們就可以看出,hashtable選用的就是通過利用奇數作為容量,那麼這麼做是否能夠讓元素分布更加均勻呢?如果有知道的同學可以跟我分析你的看法。

總結:
1.HashTable是安全執行緒的
2.HashTable底層實現跟HashMap一樣,使用的是鏈表數組。
3.HashTable的擴容公式是:2n+1,預設容量11或者2*size,選用奇數作為容量。
4.HashTable中沒有hash函數了,直接取的是Object.hashCode值作為hash值
5.HashTable中沒有再做類似HashMap中的擾動來降低碰撞機率

源碼之HashTable

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.