1

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

每个对象都有一个 id(唯一的整数字段,它是 DB 的主键),所以我的第一个想法是使用该字段作为对象的键。

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

有没有办法在 a 中使用整数键WeakHashMap

4

3 回答 3

3

在 a 中使用Integer密钥WeakHashMap不会阻止密钥被删除。Integer一旦不存在对放入 . 如果存在对不同实例的引用与 中的某个键相等(即具有相同的数值),这不会阻止该键被自动删除。IntegerMap IntegerWeakHashMap

请注意,您的值WeakHashMap不能持有对密钥的强引用 - 否则永远无法自动删除密钥。因此,为避免这种情况,只需将值添加到WeakHashMap以下内容:

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

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

如果您putWeakHashMap没有保留对密钥(即weakMap.put(new Integer(someObject.getID()),someObject))的引用的情况下输入,WeakHashMap则将能够立即自动删除它,我认为这不是您想要的。

于 2018-07-23T11:43:07.390 回答
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.
}
于 2018-07-23T11:42:04.017 回答
0

使用 Integer 作为 WeakHashMap 中的键的问题之一是 Integer 可以被垃圾收集,而它映射到的值仍在内存中使用。

如果您想要将项目作为 HashMap 中的值而不防止它们被垃圾收集,那么您应该将它们包装到 WeakReference 中并将它们用作常规 map 中的值Map<Integer, <WeakReference<Item>>,也许使用一种机制来删除未使用的键不时。

或者,如果不需要从它们的 id 中检索它们,您可以使用 Items 本身作为 WeakHashMap 的键,并使用Collections#newSetFromMap从它们创建一个集合

于 2018-07-23T11:54:58.077 回答