目标:实现一个基于LinkedHashMap的简要LRUCache类
LRUCache的特性
- LRU:least recently used,翻译为最近最少使用到,设计原则:当数据集合满了之后,添加数据时会将最先进入集合的数据进行删除。
- 缓存:查询速度快,通常基于key-value。
LinkedHashMap的特性
- 继承自HashMap:支持Kep-value以及快速查找,但增加了时间和空间上的开销。
- Entry的双向链表:有序的,插入顺序和访问顺序,默认采用插入顺序
思路
- 创建一个类,集成Iterable(用于迭代)
- 设置类的最大存储值以及初始化LinkedHashMap的初始值
- 创建存储方法Cache
- 判断cache是否存在key,如果存在就删除
- 判断cache是否已经满了,满了删除最先进入的数据
- 插入数据
- 实现Iterator,引用LinkedHashMap中的Iterator即可。
代码实现
package com.miracle.study;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
/**
* @author Miracle
* @date 2021/4/1 18:58
*/
public class LRUCache<K,V> implements Iterable<K> {
/**
* cache存储空间最大值
*/
private final int max;
/**
* 存储数据MAP
*/
private LinkedHashMap<K,V> cache;
/**
* 初始化
* @param max
*/
public LRUCache(int max){
this.max = max;
cache = new LinkedHashMap<>(max);
}
/**
* 缓存数据
* @param key
* @param value
*/
public void cache(K key, V value){
// 判断是否包含key
if (cache.containsKey(key)){
cache.remove(key);
// 判断是否空间是否充足
} else if (cache.size() >= max){
var iterator = cache.entrySet().iterator();
cache.remove(iterator.next().getKey());
}
// 插入数据
cache.put(key, value);
}
@Override
public Iterator<K> iterator() {
// 获取LinkedHashMap的迭代器
var iterator = cache.entrySet().iterator();
return new Iterator<K>() {
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public K next() {
return iterator.next().getKey();
}
};
}
public static void main(String[] args) {
LRUCache<String, Integer> lruCache = new LRUCache<>(3);
lruCache.cache("test1", 1);
lruCache.cache("test2", 2);
lruCache.cache("test3", 3);
lruCache.cache("test4", 4);
lruCache.cache("test2",5);
System.out.println("leave <-" +
StreamSupport
.stream(lruCache.spliterator(), false)
.map(x -> x.toString())
.collect(Collectors.joining("<-"))
);
}
}