对于内存感知缓存,您可能需要使用

Apache Commons collections

尤其是他们

org.apache.commons.collections.map.ReferenceMap

班级。Java特殊操作是

soft reference

. Java提供

WeakHashMap

对于弱引用,但弱引用不是您想要的缓存。Java不提供

SoftHashMap

但是

ReferenceMap

从ApacheCommons可以成为一个可行的替代品。

对软引用的记忆感知有些粗糙和不灵活。您可以使用一些Java选项来对它们进行配置,特别是

-XX:SoftRefLRUPolicyMSPerMB

值,表示软引用值在内存中保留的时间(以毫秒为单位)(当这些值不再可以直接访问时)。例如,有了它:

java -XX:SoftRefLRUPolicyMSPerMB=2500

然后,JVM将尝试将缓存值保持在比使用

威卡什地图

.

如果软引用没有提供您要查找的内容,那么您必须实现自己的缓存策略,并且确实需要手动刷新映射。这是你最初的问题。冲洗时,可以使用

clear()

方法,或者简单地创建一个新的

HashMap

. 差别应该很小,你甚至可能会有麻烦

测量

这种差异。

在“完全缓存”和“空缓存”之间交替使用也可能被认为有点粗糙,因此您可以维护多个映射。例如,您维护10个地图。当您查找缓存值时,您将查找所有映射,但当您有一个值时,只将其放在第一个映射中。当你想冲洗时,你旋转地图:第一张地图变成第二张,第二张变成第三张,依此类推,直到第十张被丢弃的地图。创建新的第一个地图。如下所示:

import java.util.*;
public class Cache {
private static final int MAX_SIZE = 500000;
private Map[] backend;
private int size = 0;
public Cache(int n)
{
backend = new Map[n];
for (int i = 0; i < n; i ++)
backend[i] = new HashMap();
}
public int size()
{
return size;
}
public Object get(Object key)
{
for (Map m : backend) {
if (m.containsKey(key))
return m.get(key);
}
return null;
}
public Object put(Object key, Object value)
{
if (backend[0].containsKey(key))
return backend[0].put(key, value);
int n = backend.length;
for (int i = 1; i < n; i ++) {
Map m = backend[i];
if (m.containsKey(key)) {
Object old = m.remove(key);
backend[0].put(key, value);
return old;
}
}
backend[0].put(key, value);
size ++;
while (size > MAX_SIZE) {
size -= backend[n - 1].size();
System.arraycopy(backend, 0, backend, 1, n - 1);
backend[0] = new HashMap();
}
return null;
}
}

上面的代码完全没有经过测试,应该用泛型进行增强。然而,它说明了主要思想:所有地图都是在阅读时测试的。(

get()

,所有新值将转到第一个映射,保留总大小,当大小超过给定限制时,将旋转映射。注意,当为一个已知的键输入一个新值时,会有一些特殊的处理。此外,在这个版本中,在查找缓存值时没有做什么特别的事情,但是我们可以“恢复”访问的缓存值:

获取()

,如果在第一个映射中找到一个值,但该值不在第一个映射中,则可以将其移动到第一个映射中。因此,频繁访问的值将永远保持缓存状态。