【发布时间】:2012-06-11 09:18:38
【问题描述】:
我不习惯处理 Java 中的软引用和弱引用,但我理解这个原理,因为我习惯于处理像 Gemfire 这样的数据网格,当内存已满时,这些数据网格会向 hdd 功能提供溢出,可能使用软引用或我猜类似的东西。
我在 Guava 中不明白的是它提供了使键变软/弱以及值变软/弱的方法。
我只是想知道例如创建具有非软值的软键有什么意义? 我的意思是,当开始收集软引用时,我们无法再通过它的键找到条目,那么为什么我们希望这些值保留在映射中?
谁能给我们一些用例:
- 弱键/软值
- 弱键/正常值
- 软键/弱值
- 软键/正常值
谢谢
编辑 我不确定我的问题是否足够精确,所以我想知道的是:
- 当一个键被收集(弱/软)时,值会发生什么(非弱/软)
- 当一个值被收集(弱/软)时,键会发生什么
- 是否将缺少部分(键或值)的条目保存在缓存中?
- 当您希望此类条目保留在缓存中时,是否有任何用例。
编辑: 正如 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() );
}
此代码产生输出:
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
如您所见,使用(已弃用)软键映射时,包含“tata”的 KeyHolder 仍然存在于映射中。
但请注意,我仍然无法使用新创建的密钥“new KeyHolder("tata");”找到我的条目
这是因为,我的键是有意义的,但它们周围的引用包装器不等于,因为它们的 equals 方法在 Guava 中没有被覆盖!
在这种情况下,是的,softKeys 没有任何意义,因为您绝对需要保留对该密钥的身份引用才能检索它。
【问题讨论】: