Java中的LRU Cache實(shí)現(xiàn)與LinkedHashMap

實(shí)現(xiàn)方法:1、LinkedHashMap。2、雙向鏈表+Map
cache寫機(jī)制:Write-through、write-behind、write-around、cache-aside

1、LinkedHashMap

構(gòu)造函數(shù)如下:

 public LinkedHashMap(int initialCapacity,
                     float loadFactor,
                     boolean accessOrder) {
    super(initialCapacity, loadFactor);
    this.accessOrder = accessOrder;
}

accessOrder默認(rèn)是false,是按照加入順序存儲(chǔ)的,傳入true即設(shè)置為按照最新訪問(wèn)順序存儲(chǔ)。
LinkedHashMap使用雙向鏈表來(lái)存儲(chǔ)LRU的訪問(wèn)順序,使用父類即HashMap來(lái)的結(jié)構(gòu)來(lái)保存數(shù)據(jù),比如雙向鏈表定義如下:

static class Entry<K,V> extends HashMap.Node<K,V> {
    Entry<K,V> before, after;   //********
    Entry(int hash, K key, V value, Node<K,V> next) {
        super(hash, key, value, next);
    }
}

在HashMap的put實(shí)現(xiàn) 中,最后一行為

afterNodeInsertion(evict);

該函數(shù)由子類實(shí)現(xiàn),在LinkedHashMap中該函數(shù)實(shí)現(xiàn)了移除最久未使用元素的功能:

void afterNodeInsertion(boolean evict) { // possibly remove eldest
    LinkedHashMap.Entry<K,V> first;
    if (evict && (first = head) != null && removeEldestEntry(first)) {
        K key = first.key;
        removeNode(hash(key), key, null, false, true);
    }
}
2、雙向鏈表+Map

可以看出LinkedHashMap就是使用雙向鏈表+Map的形式實(shí)現(xiàn)LRU緩存的,那如果自己實(shí)現(xiàn)應(yīng)該怎么寫呢?
一般遇到的使用緩存有很多種場(chǎng)景,比如為了減少讀數(shù)據(jù)庫(kù)操作,下面的例子就是對(duì)應(yīng)這種場(chǎng)景。還有比如重量級(jí)對(duì)象重用,這個(gè)就是cache沒(méi)有的時(shí)候就new一個(gè),同時(shí)更新cache。

package com.timer.database;
import com.timer.database.bean.DSimpleJob;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

public class LRUCache {

    private Map<String,DSimpleJob> cache = new HashMap<>();
    private LinkedList<String> list = new LinkedList<>();
    private int capcity;

    LRUCache(int capcity){
        this.capcity = capcity;
        Runtime.getRuntime().addShutdownHook(new Thread(this::flushCache));  //保證在JVM關(guān)閉前將cache的數(shù)據(jù)保存到數(shù)據(jù)庫(kù)
    }

    public DSimpleJob get(String key) {
        if(cache.containsKey(key)) {
            resetToHead(key);
            return cache.get(key);
        } else {         //這里可以不實(shí)現(xiàn)直接返回null,由調(diào)用者自己從數(shù)據(jù)庫(kù)讀,然后自己調(diào)用set更新cache
            if(cache.size()<capcity) {
                resetToHead(key);
                return insertNew(key);
            }else {
                cacheFull();
                return  insertNew(key);
            }
        }
    }

    public void set(String key,DSimpleJob simpleJob) {
        if(cache.containsKey(key)) {
            resetToHead(key);
            return;
        }

        if(cache.size()<capcity) {
            resetToHead(key);
        }else {
            cacheFull();
            resetToHead(key);
        }
        cache.put(key,simpleJob);
    }

    private void resetToHead(String key) {
        list.remove(key);
        list.addFirst(key);
    }

    private void cacheFull() {
        String oldest = list.removeLast();
        cache.remove(oldest);
    }

    private DSimpleJob insertNew(String key) {
        //這里應(yīng)該是從數(shù)據(jù)庫(kù)讀,然后更新,這里為了方便直接new一個(gè)了
        DSimpleJob index = new DSimpleJob();
        cache.put(key,index);
        return index;
    }

    public void setCapcity(int capcity) {
        if(this.capcity>capcity) {
            flushCache();   //將緩存數(shù)據(jù)更新到數(shù)據(jù)庫(kù)
            decreaseCap();
        } else {
            this.capcity = capcity;
        }
    }

    public void clear() {
        flushCache();
        list.clear();
        cache.clear();
    }
    private void flushCache() {
        //....
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • LinkedHashMap 的實(shí)現(xiàn)原理 LinkedHashMap 概述 HashMap 是無(wú)序的,HashMap...
    小雪的筆記閱讀 528評(píng)論 0 1
  • LinkedHashMap LinkedHashMap簡(jiǎn)介 public class LinkedHashMap<...
    史路比閱讀 578評(píng)論 0 2
  • 正值開(kāi)學(xué)季,學(xué)子們這兩天都在為開(kāi)學(xué)的事情忙活,以做足上學(xué)的準(zhǔn)備。彼時(shí),一場(chǎng)無(wú)硝煙的戰(zhàn)爭(zhēng)又將打響。這是一場(chǎng)持久...
    呼息閱讀 274評(píng)論 0 1
  • 這節(jié)課我們主要學(xué)習(xí)了Layout的用法。LinearLayout又稱作線性布局,是一種非常常用的布局,這個(gè)布局會(huì)將...
    三好市民YUHAI閱讀 225評(píng)論 0 0
  • 藥酒翻江海,頭悶聽(tīng)雨昏。
    soar1997閱讀 143評(píng)論 0 0

友情鏈接更多精彩內(nèi)容