有一种类似于哈希表的数据结构,但不经常使用的键会被删除,你知道它是什么吗?

11
我正在寻找一种数据结构,它类似于哈希表但具有大小限制。当哈希表中的项目数量达到大小限制时,应该调用清除函数来清除表中最少检索的键/值对。
这是我所工作内容的一些伪代码:
class MyClass {
  private Map<Integer, Integer> cache = new HashMap<Integer, Integer>();
  public int myFunc(int n) {
    if(cache.containsKey(n))
      return cache.get(n);
    int next = . . . ; //some complicated math.  guaranteed next != n.
    int ret = 1 + myFunc(next);
    cache.put(n, ret);
    return ret;
  }
}
发生的情况是,有一些n值会导致myFunc()被调用多次,但许多其他n值只计算一次。因此缓存可能会填满数百万次不再需要的值。我希望有一种方式可以自动删除不经常检索的元素。
这感觉像是一个已经解决的问题,但我不确定要使用哪种数据结构才能高效地解决它。是否有人可以指点我正确的方向?
更新:我知道这一定是一个已经解决的问题了。它被称为LRU缓存(最近最少使用缓存),可以通过扩展LinkedHashMap类轻松创建。以下是包含解决方案的代码:
class MyClass {
  private final static int SIZE_LIMIT = 1000;
  private Map<Integer, Integer> cache =
    new LinkedHashMap<Integer, Integer>(16, 0.75f, true) {
      protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest)
      {
        return size() > SIZE_LIMIT;
      }
  };
  public int myFunc(int n) {
    if(cache.containsKey(n))
      return cache.get(n);
    int next = . . . ; //some complicated math.  guaranteed next != n.
    int ret = 1 + myFunc(next);
    cache.put(n, ret);
    return ret;
  }
}

请参见https://dev59.com/TnVC5IYBdhLWcg3wpS7g。 - Michael Myers
6个回答

17
您正在寻找一个 LRUList/Map。请查看 LinkedHashMapremoveEldestEntry(Map.Entry) 方法可被覆盖,以在向 Map 添加新映射时自动强制执行删除过时映射的策略。

4

谢谢,这是那种情况之一,如果你已经知道答案是“LRU映射”,那么很容易找到答案,但如果你已经知道了,你就不需要去找它了。 :) - Kip

1

WeakHashMap 可能不会像你期望的那样工作... 仔细阅读文档,确保你确切地了解弱引用和强引用的区别。

我建议你查看 java.util.LinkedHashMap 并使用它的 removeEldestEntry 方法来维护缓存。如果你的计算非常耗费资源,你可能想在每次使用条目时将其移到前面,以确保只有未使用的条目才会落到集合的末尾。


1

自适应替换缓存策略旨在防止一次性请求污染您的缓存。这可能比您想要的更为复杂,但它确实直接解决了您“填满从不再需要的值”的问题。


0

看一下 WeakHashMap


这并不完全是我想要的。据我所知,弱哈希映射只是意味着在映射中存在一个键并不算作对对象的引用,因此垃圾回收器仍然可以将其删除。由于我正在使用整数,所以无法确定这是否符合我的要求。 - Kip

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接