java數據結構之WeakHashMap

1、JAVA中的四種引用類型app

  一、強引用(StrongReference):強引用是最爲廣泛的一種引用,若是對象被強引用,那麼垃圾回收器不管如何都不會回收它,當內存不足時會拋出OutOfMemoryError異常。函數

  二、軟引用(SoftReference):若是一個對象只被軟引用,當內存空間足夠時,垃圾回收器就不會回收它。當內存空間不足時,該對象就會被回收。源碼分析

  三、弱引用(WeakReference):若是一個對象只被弱引用,觸發GC時,無論內存是否足夠,垃圾回收器都會將其回收。spa

  四、虛引用(PhantomReference):若是一個對象只有虛引用在引用它,垃圾回收器是能夠在任意時候對其進行回收的,虛引用主要用來跟蹤對象被垃圾回收器回收的活動。code

 

2、WeakHashMap源碼分析對象

  因爲WeakHashMap的源碼和HashMap差很少,因此只說一些特別的地方。blog

  一、WeakHashMap對於鍵值對的引用類型爲弱引用,WeakHashMap定義了一個ReferenceQueue來儲存已經被回收了的鍵值對,當咱們須要獲取某個鍵值對的時候會先利用ReferenceQueue將WeakHashMap中已經被回收的鍵值對清除掉。繼承

        /**
     * 用來存儲已經被GC的entry
     */
    private final ReferenceQueue<Object> queue = new ReferenceQueue<>(); 

        /**
     * 從表中刪除陳舊的條目,經過和ReferenceQueue中進行對比,來進行刪除
     */
    private void expungeStaleEntries() {
        for (Object x; (x = queue.poll()) != null; ) {
            synchronized (queue) {
                @SuppressWarnings("unchecked")
                    Entry<K,V> e = (Entry<K,V>) x;
                int i = indexFor(e.hash, table.length);
    
                Entry<K,V> prev = table[i];
                Entry<K,V> p = prev;
                while (p != null) {
                    Entry<K,V> next = p.next;
                    if (p == e) {
                        if (prev == e)
                            table[i] = next;
                        else
                            prev.next = next;
                        // Must not null out e.next;
                        // stale entries may be in use by a HashIterator
                        e.value = null; // Help GC
                        size--;
                        break;
                    }
                    prev = p;
                    p = next;
                }
            }
        }
    }

...ip

private Entry<K,V>[] getTable() {
        expungeStaleEntries();
        return table;
    }
    
    public int size() {
        if (size == 0)
            return 0;
        expungeStaleEntries();
        return size;
    }
    
    public boolean isEmpty() {
        return size() == 0;
    }
    
    public V get(Object key) {
        Object k = maskNull(key);
        int h = hash(k);
        Entry<K,V>[] tab = getTable();
        int index = indexFor(h, tab.length);
        Entry<K,V> e = tab[index];
        while (e != null) {
            if (e.hash == h && eq(k, e.get()))
                return e.value;
            e = e.next;
        }
        return null;
    }

  

  二、WeakHashMap的Entry類繼承了WeakReference類,其構造函數中有一個參數queue用來傳入父類構造函數中,ReferenceQueue用來保存被GC的Entry。內存

Entry(Object key, V value, ReferenceQueue<Object> queue, int hash, Entry<K,V> next)

 

  三、WeakHashMap的初始化默認參數和HashMap相同,可是其hash方法以及resize方法不一樣。擴容的時候容量也是將容量變爲原來的兩倍

    final int hash(Object k) {
        int h = 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);
    }
    
    /**
     * 肯定entry的下標位置
     */
    private static int indexFor(int h, int length) {
        return h & (length-1);
    }
相關文章
相關標籤/搜索