我需要一个数据结构,以支持最长时间前被请求的物料的最有效的排除策略。例如,我有一些不时被要求的物品。当我的内存不足时,我想踢出数据结构(哈希图)中最旧的项。
我在考虑像Queue这样的FIFO ds smth,但是我不确定如何处理这种情况:
-> a b c d a->
a是最旧和最新的项目。如果再次添加“ a”,我需要搜索整个队列以将其删除。这是非常低效的,但是我想不出任何有效的方式来做到这一点。也许某种树形结构将访问最少的树形结构放在顶部?
Java中是否已经有这种数据结构的实现?
答案 0 :(得分:3)
LinkedHashMap
是您所追求的结构。来自the docs:
提供了一个特殊的构造函数来创建链接的哈希映射,该哈希映射的迭代顺序是其条目的最后访问顺序(从最近的访问到最近的访问)(访问顺序)。这种映射非常适合构建LRU缓存。
所以您应该只使用appropriate constructor:
Map<K, V> map = new LinkedHashMap<>(CAPACITY, LOAD_FACTOR, true);
boolean
参数确定映射是访问顺序还是插入顺序。 true
表示访问顺序。
此外,如果希望将地图用作LRU缓存,则可以创建自己的类,该类扩展LinkedHashMap
并覆盖removeEldestEntry
方法。再次,从文档:
可以重写removeEldestEntry(Map.Entry)方法,以强加一项策略,以便在向地图添加新映射时自动删除陈旧的映射。
这意味着您可以为缓存创建自己的类:
public class Cache<K, V> extends LinkedHashMap<K, V> {
private static final int MAX_ENTRIES = 100;
public Cache() {
super(SOME_INITIAL_CAPACITY, SOME_LOAD_FACTOR, true);
}
protected boolean removeEldestEntry(Entry<K, V> entry) {
return size() > MAX_ENTRIES;
}
}
用法:
Map<K, V> map = new Cache<>();
答案 1 :(得分:2)
编辑:LinkedHashMap对此具有内置功能,请参见其他答案。
您可以包装LinkedHashSet(或LinkedHashMap,具体取决于您的用例),并在访问时重新插入项目,将它们移到末尾。如果内存不足,请从前端开始删除。
class LruMap<K, V> {
LinkedHashMap<K, V> map = new LinkedHashMap<>()
V get(K key) {
V result = map.remove(key);
map.put(key, result);
return result;
}
void put(K key, V value) {
map.put(key, value);
}
void removeEldest() {
if (map.size() > 0) {
map.remove(map.keySet().iterator().next());
}
}
}