Java弱引用哈希映射 - 需要基于值的弱性而非键来删除条目。

9
因此,Java中的WeakHashMap允许创建一个映射,如果其键变得弱,则删除其条目。但是,我如何创建一个Map,当地图中的值变得弱时将其条目删除?我希望使用映射作为全局哈希表,根据它们的ID跟踪对象。
ID --->  Object Address

Key ---> Value

(其中ID是文本字符串)
我希望在对象地址变为弱引用时删除键值对,而不是指向它们的字符串。有人对此有什么想法吗?

你可能会觉得这篇文章有趣:http://weblogs.java.net/blog/enicholas/archive/2006/05/understanding_w.html - Lucas Zamboulis
谢谢你提供的链接,卢卡斯 - 这是一个很好的讨论主题。 - Binaromong
4个回答

10

例如在Guava中支持这样的映射:

Map<..., ...> m = new MapMaker().weakValues().makeMap();

这样做不行,它只会将值包装在弱引用中,但当值被垃圾回收时不会删除条目... - pgras
2
@pgras:不,它也会删除条目。唯一的区别是WeakHashMap在访问映射时删除过期条目,而Guava的实现则在后台线程中删除它们(FinalizableReferenceQueue)。 - axtavt
你是对的,根据文档,“键或值被垃圾回收器回收的条目将立即从映射中消失”。 - pgras
非常感谢您,这似乎是我见过的最佳解决方案。不幸的是,它需要将如此大的JAR文件添加到构建中,但API似乎很棒。 - Binaromong

3

你为什么希望条目被垃圾回收?我看到两个原因:

  1. 避免内存泄漏(避免在Map中保留指向无效对象的弱引用)
  2. 如果对象被垃圾回收,myMap.get(myKey)应该返回null。

解决方案:使用常规HashMap:

Map<String, WeakReference<Object>>

如果只有第二个问题,那么只需使用myMap.get(myKey).get()。

如果您还需要删除条目,请查看此文章,该文章介绍了一个softHashMap并适应使用weakReferences...


2

API已经给出了答案:

实现注意事项:WeakHashMap中的值对象由普通的强引用持有。因此,应当注意确保值对象不会直接或间接地强引用自己的键,否则将阻止键被丢弃。请注意,一个值对象可能通过WeakHashMap本身间接地引用它的键;也就是说,一个值对象可能强引用某个其他键对象,而该键对象的关联值对象又强引用第一个值对象的键。解决这个问题的方法之一是在插入前将值本身包装在WeakReferences中,例如:m.put(key, new WeakReference(value)),然后每次获取时进行拆包。


@pgras:当一个值仅通过弱引用从地图中引用时,它可以被回收。此时,如果从该值引用了键,则键也可以被回收。 - subsub
@subsub: 如果一个键是弱引用、软引用或虚引用,那么它可能会被回收,但如果您想将其用作键,则该键必须是强引用。 - pgras
@pgras:不需要具有强连通性的键,哈希图是通过散列搜索的。键仅用于确保相等性。如果键消失了,那么就不会有相等性了。 - subsub
@pgras:我同意使用interned字符串作为键是一个问题,但值仍然可以被回收利用。然而(上次我检查时)只有字符串字面量会自动interned,并且String.equals检查内容是否相等。所以我不理解你的最后一点。 - subsub
@subsub:一开始我认为你的解决方案行不通,现在我看到只要你保证不从地图外部保留对键的强引用,并且从值内部保留对键的强引用,它就会起作用。在我看来,这使得它成为一个复杂的解决方案,而更简单的解决方案是可能的,可以保持对键的强引用,而不强制你的值引用键。例如,Guava的解决方案对我来说似乎更好... - pgras
显示剩余3条评论

2
你可以做类似于WeakHashMap的事情,但是针对的是值而不是键:将你的值包装在WeakReferences中,并将它们与在map中保存的ReferenceQueue关联起来。每当访问map时,检查ReferenceQueue是否有任何添加的内容,如果有,则从map中删除其条目。您需要创建一个持有键的WeakReference子类,以便知道要删除哪个条目。您还需要在查询map的方法(get和containsKey、迭代器方法等)中添加一个检查,以检查检索到的WeakReference是否实际包含一个值(请记住禁止空值,或使用一个特殊的标记对象来表示它们)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接