Java和Android中的缓存算法

有这么一种应用场景:我们需要定时缓存一些数据,但又不想占用内存太多,所以我们会给缓存设置一定的容量大小,如果缓存的数据超过了设置的容量,就需要删除其中一些数据腾出空间来缓存新的数据。

那问题来了,删除掉哪些数据呢,有三种方案:

1,按存入顺序,删除缓存中最先存入的数据

2,按使用时间,删除最长时间没有使用的数据

3,按使用频率,删除一段时间内访问次数最少的数据

这三种方案就是三种缓存算法,分别为:FIFO(First In,First Out)、LRU(Least Recently Used)、LFU(Least Frequently Used)。

本文使用LinkedHashMap实现FIFO和LRU两种算法。

/**
 * 缓存使用容量超过设定的容量,则删除最前面的数据
 */
public class XCache<K, V> {
    //默认的缓存大小
    private static final int DEFAULT_CACHE_SIZE = 10;
    //加载因子,使用容量超过(设定容量*加载因子),就会自动扩容
    private static final float DEFAULT_LOAD_FACTOR = 0.75f;
    /**
     * 缓存模式,默认为FIFO
     * FIFO:最新存进来的元素放在后面,优先删除先存入的数据
     * LRU:最近调用过的元素放在后面,优先删除最长时间没有使用的数据
     */
    private Mode mode = Mode.FIFO;
    //缓存容量,默认为10
    private int cacheSize = DEFAULT_CACHE_SIZE;
    //用来实现缓存
    private LinkedHashMap<K, V> map;
    //缓存删除监听
    private OnRemoveListener<K, V> removeListener;

    public XCache() {
        this(DEFAULT_CACHE_SIZE);
    }

    public XCache(int cacheSize) {
        this(cacheSize, Mode.FIFO);
    }

    public XCache(int cacheSize, Mode mode) {
        this.mode = mode;
        this.cacheSize = cacheSize;
        init();
    }

    public void setMode(Mode mode) {
        this.mode = mode;
    }

    public void setCacheSize(int cacheSize) {
        this.cacheSize = cacheSize;
    }

    public void setRemoveListener(OnRemoveListener<K, V> removeListener) {
        this.removeListener = removeListener;
    }

    private void init() {
        map = new LinkedHashMap<K, V>(cacheSize, DEFAULT_LOAD_FACTOR, mode == Mode.FIFO ? false : true) {
            @Override
            protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
                if (size() > cacheSize && removeListener != null)
                    removeListener.remove(eldest.getKey(), eldest.getValue());
                //设置缓存删除条件
                //当缓存容量大于设定容量时,按算法进行删除
                return size() > cacheSize;
            }
        };
    }

    //把数据放入缓存
    public synchronized void put(K key, V value) {
        map.put(key, value);
    }

    //从缓存中读取数据
    public synchronized V get(K key) {
        return map.get(key);
    }

    //从缓存中主动删除数据
    public synchronized V remove(K key) {
        return map.remove(key);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<K, V> entry : map.entrySet()) {
            sb.append(String.format("%s:%s ", entry.getKey(), entry.getValue()));
        }
        return sb.toString();
    }

    public enum Mode {
        FIFO, LRU;
    }

    public interface OnRemoveListener<K, V> {
        void remove(K key, V value);
    }
}
调用示例

public class Test {
    public static void main(String[] args) {
        XCache<String, Integer> xCache = new XCache<>(10, XCache.Mode.LRU);
        xCache.setRemoveListener(new XCache.OnRemoveListener<String, Integer>() {
            @Override
            public void remove(String key, Integer value) {
                System.out.println("remove>>>" + key + "==" + value);
            }
        });
        for (int i = 0; i < 20; i++) {
            xCache.put("key" + i, i);
        }

        //模拟调用
        xCache.get("key" + 15);

        System.out.println(xCache.toString());

    }
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值