3.HashMap的數據結構是什么?如何實現的。和HashTable,ConcurrentHashMap的區別


HashMap的數據結構:

數組+鏈表,數組中元素是個鏈表,存儲Key的hashcode碰撞的元素

其中元素的節點為:

    static class Node<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        V value;
        Node<K,V> next;

        Node(int hash, K key, V value, Node<K,V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }

        public final K getKey()        { return key; }
        public final V getValue()      { return value; }
        public final String toString() { return key + "=" + value; }

        public final int hashCode() {
            return Objects.hashCode(key) ^ Objects.hashCode(value);
        }

        public final V setValue(V newValue) {
            V oldValue = value;
            value = newValue;
            return oldValue;
        }

        public final boolean equals(Object o) {
            if (o == this)
                return true;
            if (o instanceof Map.Entry) {
                Map.Entry<?,?> e = (Map.Entry<?,?>)o;
                if (Objects.equals(key, e.getKey()) &&
                    Objects.equals(value, e.getValue()))
                    return true;
            }
            return false;
        }
    }

每個Node含有指向下一個Node的指針

數組(HashMap大小)的初始長度16

    /**
     * The default initial capacity - MUST be a power of two.
     */
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

數組的增長因子,0.75

/**
     * The load factor used when none specified in constructor.
     */
    static final float DEFAULT_LOAD_FACTOR = 0.75f;

 

HashMap的實現重點需要注意的在兩個方面,一個是鏈表結構,一個是table的resize()

HashMap處理hashcode碰撞的方式用鏈表,hashcode相同的元素頭尾相連組成一個單鏈,並把最開始的那個節點存儲在數組中,訪問的時候,先通過hash(key)找到數組下標,再迭代單鏈找到equals()的value,然后返回

resize的時候,如果當前數組的占用率達到負載因子0.75,則會觸發一次resize(),增長量為原來容量(table.length)的一倍,newCap = oldCap << 1

然后把老數組的數據遷移到新數組

//=============================================================分割線====================================================================

HashMap和HashTable的區別:

他們的結構差不多,只不過HashTable是線程安全的,HashTable是所有暴露的操作都加鎖,synchronized,這種情況下性能比較低,容易引起活躍性問題

HashTable跟java.util.Collections#synchronizedMap很接近

HashMap允許key和value為null

HashTable不允許key和value為null

 

ConcurrentHashMap也是線程安全的,是采用CAS的方式來處理並發操作,如果單鏈比較長就坍縮為一個紅黑樹,logn的時間復雜度

ConcurrentHashMap要分jdk1.8之前還是之后

1.8之前的ConcurrentHashMap是采用分段(Segment)的方式,加鎖時直接在Segment上加鎖,縮小了加鎖范圍,提高了性能

1.8之后的ConcurrentHashMap是重寫的,加鎖范圍進一步縮小,采用CAS將加鎖范圍縮小到單個數組元素

 性能上ConcurrentHashMap比前面的要高

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM