[Java]在Java中限制Map數量,若超過移除舊資料

一般來說使用MAP時就算限定了數量

new HashMap(10)

但是在使用put的時候會連帶使用到addEntry

一般來說使用MAP時就算限定了數量

new HashMap(10)

但是在使用put的時候會連帶使用到addEntry

public V put(K key, V value) {
    if (key == null)
        return putForNullKey(value);
    int hash = hash(key.hashCode());
    int i = indexFor(hash, table.length);
    for (Entry e = table[i]; e != null; e = e.next) {
        Object k;
        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
            V oldValue = e.value;
            e.value = value;
            e.recordAccess(this);
            return oldValue;
        }
    }

    modCount++;
    addEntry(hash, key, value, i);
    return null;
}

然而在addEntry當中會判斷如果MAP中的數量大於限定數量時

void addEntry(int hash, K key, V value, int bucketIndex) {
    Entry e = table[bucketIndex];
    table[bucketIndex] = new Entry(hash, key, value, e);
    if (size++ >= threshold)
        resize(2 * table.length);
}

會去使用resize進行擴充,而擴充的數量是限定的兩倍

void resize(int newCapacity) {
    Entry[] oldTable = table;
    int oldCapacity = oldTable.length;
    if (oldCapacity == MAXIMUM_CAPACITY) {
        threshold = Integer.MAX_VALUE;
        return;
    }

    Entry[] newTable = new Entry[newCapacity];
    transfer(newTable);
    table = newTable;
    threshold = (int)(newCapacity * loadFactor);
}

也就是說就算一開始設定了數量為10,當裡面的元素超過10之後會自動變成20

要解決這個問題最直覺的作法就是去覆寫put

不過看到put原本的內容.....

我沒有把握弄改好..還是不要亂來吧

後來發現HashMap下面還有一個子類別叫做LinkedHashMap

它跟HashMap不同的地方是LinkedHashMap會去紀錄新增的順序,但HashMap不會

LinkedHashMap中有一個函式叫做removeEldestEntry

從字面上來翻譯,就是移除最舊項目

官方API文件也給了一個覆寫範例

private static final int MAX_ENTRIES = 100;

protected boolean removeEldestEntry(Map.Entry eldest) {

    return size() > MAX_ENTRIES;

}

如果數量超過一百就移除最先put進來的元素

這不就是我們需要的東西嗎!!!

馬上來測試看看

Map h = new LinkedHashMap(){
    private static final int MAX_ENTRIES = 10;
    
    protected boolean removeEldestEntry(Map.Entry eldest) {
        return size() > MAX_ENTRIES;
    }
};

for(int i = 1; i < 21; i++){
    h.put(new Integer(i), new Integer(i));
}

System.out.println(h.size());

最後輸出的結果是10

但如果把LinkedHashMap改成HashMap會輸出20

我經營的論壇: 台論之星

塵世中一位載浮載沉之小小工程師

michael-chen@jiebu-lang.com