Seb*_*ber 8 java caching guava
我不习惯处理Java中的Soft和Weak引用,但我理解这个原理,因为我习惯于处理像Gemfire这样的数据网格,它在内存已满时提供溢出到hdd功能,可能使用软引用或类似的东西我猜测.
在番石榴中我不明白的是它提供了使键变软/弱的方法,以及值软/弱的方法.
我只是想知道用非软值创建软键的例子是什么意思?我的意思是,当开始收集软引用时,我们无法通过其键找到条目,那么为什么我们希望这些值保留在地图中?
有人可以给我们一些用例:
谢谢
编辑 我不确定我的问题是否足够精确,所以我想知道的是:
编辑: 正如Kevin Bourillon的回答所讨论的,最后我想我明白为什么使用软键并不意味着什么.原因如下:
static class KeyHolder {
final private String key;
public KeyHolder(String key) {
this.key = key;
}
public String getKey() {
return key;
}
@Override
public boolean equals(Object o) {
KeyHolder that = (KeyHolder)o;
boolean equality = this.getKey().equals(that.getKey());
return equality;
}
@Override
public int hashCode() {
return key != null ? key.hashCode() : 0;
}
@Override
public String toString() {
return "KeyHolder{" +
"key='" + key + '\'' +
'}';
}
}
public static void main(String[] args) {
System.out.println("TESTING WEAK KEYS");
testMap( new MapMaker().weakKeys().<KeyHolder,String>makeMap() );
System.out.println("\n\n");
System.out.println("TESTING SOFT KEYS");
testMap(new MapMaker().softKeys().<KeyHolder, String>makeMap());
System.out.println("\n\n");
System.out.println("TESTING SOFT REFERENCES");
KeyHolder key1 = new KeyHolder("toto");
KeyHolder key2 = new KeyHolder("toto");
SoftReference<KeyHolder> softRef1 = new SoftReference<KeyHolder>(key1);
SoftReference<KeyHolder> softRef2 = new SoftReference<KeyHolder>(key2);
System.out.println( "equals keys? " + key1.equals(key2) );
System.out.println( "equals ref? " + softRef1.equals(softRef2) );
}
private static void testMap(Map<KeyHolder,String> map) {
KeyHolder strongRefKey = new KeyHolder("toto");
KeyHolder noStrongRefKey = new KeyHolder("tata");
map.put(strongRefKey,"strongRef");
map.put(noStrongRefKey,"noStrongRefKey");
// we replace the strong reference by another key instance which is equals
// this could happen for exemple in case of serialization/deserialization of the key
noStrongRefKey = new KeyHolder("tata");
System.gc();
System.out.println( "strongRefKey = " + map.get(strongRefKey) );
System.out.println( "noStrongRefKey = " + map.get(noStrongRefKey) );
System.out.println( "keyset = " + map.keySet() );
}
Run Code Online (Sandbox Code Playgroud)
此代码生成输出:
TESTING WEAK KEYS
strongRefKey = strongRef
noStrongRefKey = null
keyset = [KeyHolder{key='toto'}]
TESTING SOFT KEYS
strongRefKey = strongRef
noStrongRefKey = null
keyset = [KeyHolder{key='tata'}, KeyHolder{key='toto'}]
TESTING SOFT REFERENCES
toto == toto -> true
equals keys? true
equals ref? false
Run Code Online (Sandbox Code Playgroud)
如您所见,使用(不推荐使用的)软键映射,包含"tata"的KeyHolder仍然存在于地图中.但请注意,我仍然无法使用新创建的键找到我的条目" new KeyHolder("tata");"
这是因为,我的键有意义地等于,但是它们周围的引用包装器不等于因为它们的等于方法在Guava中没有被覆盖!
在这种情况下,是的,softKeys并不意味着什么,因为你绝对需要保持对该密钥的身份引用才能检索它.
Kev*_*ion 13
softKeys从来没有意义,所以我们删除了方法.softValues假设值实例在缓存之外的其他方式也不可达,这是软refs有意义的唯一方法.
然后使用weakKeys基本归结为你是否想要密钥的身份相同.如果密钥覆盖equals,你需要的是平等的行为,你不能使用它.如果你想要身份,那么weakKeys你是如何得到它的,这也是有道理的,因为一旦所有其他对密钥的引用都已经GC了,无论如何都无法查找该条目,所以它也可能被删除.
我实际上并不完全清楚什么时候weakValues有用,并且会调查它.它可能是一个weakKeys不是选项(比如Integer键)的情况,并且值通常通过其他方式强烈引用,例如某种会话对象,但当该对象消失时,它表示没有人会在缓存中寻找这个.不过,当我这么说时,它似乎有点牵强.