带有不可变密钥的Java WeakHashMap

时间:2018-07-23 11:29:40

标签: java immutability weakhashmap

我想对在内存中存在很短时间的对象使用WeakHashMap

每个对象都有一个id(唯一整数字段,它是数据库中的主键),所以我的第一个念头是使用该字段作为对象的键。

但是,Integer是不可变的,因此AFAIK哈希将生成另一个不可变的Integer,因此只要任何其他不相关的对象指向该对象,该对象就不会被GC化。

是否可以在WeakHashMap中使用整数键?

3 个答案:

答案 0 :(得分:3)

Integer中使用WeakHashMap键不会阻止键被删除。 一旦没有对放置在Integer中的相同 Integer实例的引用,就可以对Map键进行垃圾回收。如果存在对不同 Integer个实例的引用与WeakHashMap中的某个键相等(即具有相同的数值),则不会阻止该键被自动删除

请注意,您的WeakHashMap的值不能持有对该键的强引用-否则,该键永远不会被自动删除。因此,为避免这种情况,只需将值添加到WeakHashMap中,如下所示:

Integer key = new Integer(someObject.getID());
weakMap.put(key,someObject);

现在,一旦不再保留对Integer变量所引用的key实例的引用,WeakHashMap将可以自由地自动删除它。

如果您在putWeakHashMap中的条目没有保留对键(即weakMap.put(new Integer(someObject.getID()),someObject))的引用,则WeakHashMap将能够立即自动将其删除,我认为这不是您想要的。

答案 1 :(得分:1)

如您所说,WeakHashMap将无法提供所需的功能。 JavaDocs声明以下内容

  

因此应注意确保值对象不   直接或间接强烈引用自己的键,   因为这样可以防止密钥被丢弃。

因此,您可以实现“ WeakValueMap”。但这并不像听起来那样复杂。您只需将WeakReference包装在类型定义中

Map<Integer, WeakReference<YourType>> cache ...

或者您可以围绕它实现包装器实现。

public class Cache<K, V> implements Map<K, V> {
   private final Map<K, V> store = new HashMap<>();

  // implement put, get, etc.
}

答案 2 :(得分:0)

使用Integer作为WeakHashMap中的键的问题之一是,可以将Integer进行垃圾回收,而将其映射的值仍在内存中使用。

如果您想要的是将这些项目作为HashMap中的值,而又不阻止它们被垃圾回收,那么您应该将它们包装到WeakReference中,并在常规映射Map<Integer, <WeakReference<Item>>中将其用作值,也许具有不时删除未使用密钥的机制。

或者,如果不需要从其ID中检索它们,则可以将Items本身用作WeakHashMap的键,并使用Collections#newSetFromMap

从其中创建一个集