java HashMap

HashMap 的性能因子

1. 容量:表示桶位的數量。html

2. 初始容量: 表在建立是所擁有的桶位數。數據結構

  •   若是你知道將要在HashMap存儲多少項,建立一個初始容量合適的HashMap將能夠避免自動再散列的開銷
    /**
     * The default initial capacity - MUST be a power of two.
     */
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; //默認大小

3. 尺寸: 表中當前存儲的項數。函數

4. 負載因子:尺寸/容量。 負載因子小的表衝突的可能性小,插入和查找的速度也相對較快(但會減慢使用迭代器進行遍歷的過程)。HashMap和HashSet都具備容許你指定負載因子的構造器,表示當負載狀況達到負載因子的水平時,容器將自動增長容量。實現方法是使容量加倍,並將現有對象分配到新的桶位集中。性能

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

 

HashMap構造器

HashMap(int initialCapacity, float loadFactor);
 initialCapacity爲初始容量, loadFactor爲負載因子
       /**
      * Constructs an empty <tt>HashMap</tt> with the specified initial
      * capacity and load factor.
      *
      * @param  initialCapacity the initial capacity
      * @param  loadFactor      the load factor
      * @throws IllegalArgumentException if the initial capacity is negative
      *         or the load factor is nonpositive
      */
    public HashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                            initialCapacity);
        if (initialCapacity > MAXIMUM_CAPACITY)  // MAXIMUM_CAPACITY爲最大容量
            initialCapacity = MAXIMUM_CAPACITY;
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: " +
                            loadFactor);
        this.loadFactor = loadFactor;


        this.threshold = tableSizeFor(initialCapacity); // tableSizeFor(initialCapacity) 會返回x(x表示2的整數次冪)
        //threshold是一個闕值,它等於 負載因子*尺寸, 固然這裏暫時等於容量
        //當調用resize函數後纔開始真正分配空間(槽位),這時才賦給threshold真正意義上的值
    }

 

來看看tableSizeFor的實現(我的絕對想不到這麼高大上的方法)優化

    /**
     * Returns a power of two size for the given target capacity.
     */
    static final int tableSizeFor(int cap) {
        int n = cap - 1;  //這裏是由於考慮到cap爲2的整數次冪的狀況

        //1. 假設此時n的二進制最高位1在第i位(最低位爲第0位)

        n |= n >>> 1;

        //2. 此時n的二進制第i, i-1位都爲1

        n |= n >>> 2;

        //3. 此時n的二進制第i, i-1,  i-2, i-3位都爲1

        n |= n >>> 4;

        //4. 此時n的二進制第i, i-1,  i-2, i-3, i-4, i-5, i-6, i-7位都爲1(固然,嚴謹點應該再假設i>7)

        n |= n >>> 8;
        //5.---------
        n |= n >>> 16;
        //6.---------
        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    }

 

添加元素

 

    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }

    /**
     * Implements Map.put and related methods
     *
     * @param hash hash for key
     * @param key the key
     * @param value the value to put
     * @param onlyIfAbsent if true, don't change existing value
     * @param evict if false, the table is in creation mode.
     * @return previous value, or null if none
     */
    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        if ((p = tab[i = (n - 1) & hash]) == null) // 判斷是否發生衝突
            tab[i] = newNode(hash, key, value, null);  // 沒反生衝突,直接放入第i個槽位
        else {
        //執行到這裏,表示發生衝突了
            Node<K,V> e; K k;
            if (p.hash == hash &&
                    ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;  //若是key相等,直接把新value覆蓋原value
            else if (p instanceof TreeNode) //判斷當前解決衝突所用的數據結構是否是TreeNode(紅黑樹)
                                            //這是當衝突過多(某個槽位衝突數超過TREEIFY_THRESHOLD=8)時,
                                            //HashMap的優化方式
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
            else {
            // 執行到這裏說明當前解決衝突所用結構是鏈表
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) {
                        p.next = newNode(hash, key, value, null);
                        if (binCount >= TREEIFY_THRESHOLD - 1) // 衝突數超過TREEIFY_THRESHOLD
                                                               // 用紅黑樹代替鏈表
                            treeifyBin(tab, hash);
                        break;
                    }
                    if (e.hash == hash &&
                            ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }
            if (e != null) { //若是map存在與新key相等的key,直接把新value覆蓋原value
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
        }
        ++modCount;
        if (++size > threshold) //判斷當前尺寸是否大於闕值(即負載是否大於負載因子)
            resize();
        afterNodeInsertion(evict);
        return null;
    }

 

博客園(FOREVER_ENJOY):http://www.cnblogs.com/zyx1314/p/5359434.htmlthis

本文版權歸做者全部;歡迎轉載!請註明文章做者和原文鏈接spa

相關文章
相關標籤/搜索