首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

WeakHashMap 源碼深度解析:基於弱引用的自動回收 Map 實現原理

     編輯:Java 綜合教學

WeakHashMap 內部機制全面剖析

WeakHashMap 結合 WeakReference 與 HashMap,實現 Key 可被 GC 自動回收的 Map,極適合緩存場景。

一、初始化

public WeakHashMap(int initialCapacity, float loadFactor) {
    if (initialCapacity < 0) throw new IllegalArgumentException(...);
    int capacity = 1;
    while (capacity < initialCapacity) capacity <<= 1;
    table = newTable(capacity);
    this.loadFactor = loadFactor;
    threshold = (int)(capacity * loadFactor);
    useAltHashing = sun.misc.VM.isBooted() && (capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
}

與 HashMap 類似,計算 2 的冪次容量,創建 Entry 數組。

二、核心差異:put() 與 getTable()

public V put(K key, V value) {
    Object k = maskNull(key);              // 1. 包裝 null key
    int h = hash(k);
    Entry<K,V>[] tab = getTable();         // 2. 關鍵:調用 getTable() 清理過期條目
    int i = indexFor(h, tab.length);
    for (Entry<K,V> e = tab[i]; e != null; e = e.next) {
        if (h == e.hash && eq(k, e.get())) { // 3. 使用 eq() 比較,e.get() 獲取弱引用指向的對象
            V oldValue = e.value;
            if (value != oldValue) e.value = value;
            return oldValue;
        }
    }
    modCount++;
    Entry<K,V> e = tab[i];
    tab[i] = new Entry<>(k, value, queue, h, e); // 4. 新 Entry 關聯 ReferenceQueue
    if (++size >= threshold) resize(tab.length * 2);
    return null;
}

三、自動清理機制:expungeStaleEntries()

private Entry<K,V>[] getTable() {
    expungeStaleEntries(); // 每次操作前清理
    return table;
}

private void expungeStaleEntries() {
    for (Object x; (x = queue.poll()) != null; ) {
        synchronized (queue) {
            Entry<K,V> e = (Entry<K,V>) x;
            int i = indexFor(e.hash, table.length);
            Entry<K,V> prev = table[i], p = prev;
            while (p != null) {
                Entry<K,V> next = p.next;
                if (p == e) {
                    if (prev == e) table[i] = next;
                    else prev.next = next;
                    e.value = null; // 幫助 GC
                    size--;
                    break;
                }
                prev = p; p = next;
            }
        }
    }
}

流程: 遍歷 ReferenceQueue 中已失效的弱引用,定位哈希桶,從鏈表移除,置空 value,size--。

四、Entry 結構

Entry結構

private static class Entry<K,V> extends WeakReference<Object>> implements Map.Entry<K,V> {
    V value;
    final int hash;
    Entry<K,V> next;
    Entry(Object key, V value, ReferenceQueue<Object> queue, int hash, Entry<K,V> next) {
        super(key, queue); // 關鍵:傳入 queue,Key 被 GC 後自動入隊
        this.value = value;
        this.hash = hash;
        this.next = next;
    }
    // getKey() 返回 get() 獲取的強引用對象
}

五、remove() 等其他操作

均先調用 getTable() 觸發清理,邏輯與 HashMap 一致。

六、適用場景與總結

  • 緩存存儲:Key 不再被外部引用時自動失效,無需手動清理。
  • 學習範例:展示弱引用 + 引用隊列 + 定期清理的經典模式。

注意:WeakHashMap 的 Key 必須正確實現 equals/hashCode,且不應為長期強引用對象,否則失去自動回收意義。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved