LinkedHashMap实现热数据缓存

LinkedHashMap实现热数据缓存

Scroll Down

HashMap 或者 ConcurrentHashMap

是在Java 中使用最简单的本地缓存方式。ConcurrentHashMap多用于缓存更新的场景,因为它是线程安全的,可以保证数据的一致性。

LinkedHashMap类

提供了一个==自动清理最老元素==的功能,可以作为一个LRU(Least Recently Used ,表示最近最少使用)缓存使用。

将LinkedHashMap 改造成缓存

需要重写 LinkedHashMap 中 removeEldestEntry(Map.Entry<K,V> eldest) 这个方法。

默认返回false,不移除老的key,需要开发人员自己改造。

    protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
        return false;
    }

自定义MyLruCache,来实现一个自动清理老数据,将热数据放在队尾。

package com.wuxiongwei.java.hashmap.linkedhashmap;

import java.util.LinkedHashMap;


public class MyLruCache<K, V> extends LinkedHashMap<K, V>
{
    private static final long serialVersionUID = 4504158311663914052L;



    @Override
    public V put(K key, V value) {
        //或者Map<String, String> cache = Collections.synchronizedMap(new LruCache<String, String>(3));
//        synchronized (this) {
            return super.put(key, value);
//        }
    }

    private int maxCacheSize;

    public MyLruCache(int maxCacheSize) {

        // 第三个参数为 accessOrder,默认为false。
        // 表示按照按照访问顺序排列元素,最近访问的元素会排在队末尾
        super(maxCacheSize, 0.75f, true);

        this.maxCacheSize = maxCacheSize;

    }

    @Override
    protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {
        //默认返回false,队列会越来越大
        // 当达到预设缓存上限时删除最老元素
        return this.size() >= maxCacheSize + 1;
    }
}


package com.wuxiongwei.java.hashmap.linkedhashmap;

import java.util.HashMap;
import java.util.Map;

public class Clinet1 {
    public static void main(String[] args) {
        MyLruCache<String, String> cache = new MyLruCache<String, String>(3);
        //如果MyLruCache本身不是线程安全的,可以使用Collections.synchronizedMap来打到线程安全的效果
        //Map<String, String> cache = Collections.synchronizedMap(new MyLruCache<String, String>(3));


        //初始化三个key
        cache.put("k1", "v1");
        System.out.println("put1:"+cache);
        cache.put("k2", "v2");
        System.out.println("put2:"+cache);
        cache.put("k3", "v3");
        System.out.println("put3:"+cache);

        //因为大小是3,添加第四个时会移除k1
        cache.put("k4", "v4");
        System.out.println("put4:"+cache);

        //访问一次 k2,k2对应的元素就会排在队尾部,被看做最新元素
        cache.get("k2");
        System.out.println("get5:"+cache);

        Map<String,String> multiKV = new HashMap<String,String>();
        multiKV.put("k5", "k5");
        multiKV.put("k6", "k6");
        cache.putAll(multiKV);
        System.out.println("get6:"+cache);
    }
}

输出结果

put1:{k1=v1}
put2:{k1=v1, k2=v2}
put3:{k1=v1, k2=v2, k3=v3}
put4:{k2=v2, k3=v3, k4=v4}
get5:{k3=v3, k4=v4, k2=v2}
get6:{k2=v2, k5=k5, k6=k6}

从例子中可见,通过简单的方式就可以快速实现一个LRU缓存类。