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

J2ME 實用類:SimpleCache 基於 LRU 的輕量級緩存實現

     編輯:J2ME

前言

J2ME 無標準緩存工具。SimpleCache 以 Hashtable + 雙向鏈表 實現 **O(1) 獲取/放入**、**LRU 淘汰**、**固定容量上限**,代碼 < 80 行,零依賴,適合圖片緩存、網絡響應緩存、RMS 熱數據緩存。

核心數據結構


class Entry {
    Object key, value;
    Entry prev, next; // 雙向鏈表指針
    Entry(Object k, Object v) { key = k; value = v; }
}
  • Hashtable cacheMap:Key → Entry (O(1) 查找)。
  • Entry head, tail:虛擬頭尾節點,構建 LRU 雙向鏈表。
    頭部 (head.next) = 最近使用 (MRU),尾部 (tail.prev) = 最久未使用 (LRU)。
  • int capacity:最大條目數。

完整實現


public class SimpleCache {
    private Hashtable cacheMap = new Hashtable();
    private Entry head = new Entry(null, null), tail = new Entry(null, null);
    private int capacity;

    public SimpleCache(int capacity) {
        this.capacity = capacity;
        head.next = tail; tail.prev = head;
    }

    // 獲取並標記為最近使用
    public Object get(Object key) {
        Entry e = (Entry) cacheMap.get(key);
        if (e == null) return null;
        moveToHead(e);
        return e.value;
    }

    // 放入或更新
    public void put(Object key, Object value) {
        Entry e = (Entry) cacheMap.get(key);
        if (e != null) {
            e.value = value;
            moveToHead(e);
        } else {
            e = new Entry(key, value);
            cacheMap.put(key, e);
            addToHead(e);
            if (cacheMap.size() > capacity) {
                removeLRU();
            }
        }
    }

    // 移除指定鍵
    public void remove(Object key) {
        Entry e = (Entry) cacheMap.remove(key);
        if (e != null) unlink(e);
    }

    // 核心鏈表操作
    private void addToHead(Entry e) {
        e.next = head.next; e.prev = head;
        head.next.prev = e; head.next = e;
    }
    private void unlink(Entry e) {
        e.prev.next = e.next; e.next.prev = e.prev;
    }
    private void moveToHead(Entry e) {
        unlink(e); addToHead(e);
    }
    private void removeLRU() {
        Entry lru = tail.prev;
        unlink(lru);
        cacheMap.remove(lru.key);
    }
}

使用示例:圖片緩存


// 容量 20 張圖片
SimpleCache imageCache = new SimpleCache(20);

// 獲取圖片
Image img = (Image) imageCache.get("/res/bg.png");
if (img == null) {
    img = loadImage("/res/bg.png"); // 真實加載
    imageCache.put("/res/bg.png", img);
}
g.drawImage(img, x, y, Graphics.TOP | Graphics.LEFT);

J2ME 專項優化

  • 無泛型: 全 Object,調用方轉型。
  • 同步可選: 單線程環境無需同步;多線程請在調用端 synchronized(cache) 或內部加 synchronized (微增開銷)。
  • 弱引用擴展: 若需 GC 協助回收大對象 (如大圖),可將 value 改為 WeakReference (需 CLDC 1.1/外部庫),get() 時檢查 ref.get() != null。
  • 統計擴展: 增加 hitCount/missCount 監控命中率。

總結

SimpleCache 以經典 HashMap + 雙向鏈表 結構,在 J2ME 受限環境下提供生產級 LRU 緩存能力。理解其核心不變量 (head.next=MRU, tail.prev=LRU),即可靈活擴展 TTLR、分級緩存、預熱策略等高級功能。

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