为什么存在WeakHashMap,但不存在WeakSet?

82

来源自J. Bloch

内存泄漏的一个主要源头之一是监听器。为确保回调能够及时垃圾回收,最好的方法是仅使用弱引用存储它们,例如仅将其作为键存储在WeakHashMap中。

那么,为什么Java集合框架中没有WeakSet呢?(参考)


1
Stas,你能接受Mart的被点赞的正确答案,而不是Martin的被踩的错误答案吗? - toolforger
虽然Joshua Bloch为Java程序员提供了很多合理的建议,但这似乎是一个可怕的例外。将监听器存储到WeakHashMap中永远不会“确保回调及时进行垃圾回收”,而是使它们变得非常不确定。垃圾收集器只有在内存不足时才会运行,因此,这些弱监听器可能会悬挂很长时间并仍在执行,但更糟糕的是,当您仍需要它们时,这些监听器可能会出现错误消失,因为现在需要实际上无关的强引用来保持它们活动状态。 - Holger
你可以(甚至鼓励)明确地删除它们,但使用弱引用集合可以确保它们不会通过这个途径泄漏出去。 - Donal Fellows
2个回答

205

Collections.newSetFromMap

Set<Object> weakHashSet = 
    Collections.newSetFromMap(
        new WeakHashMap<Object, Boolean>()
    );
根据 Collections.newSetFromMap 文档,传递一个 WeakHashMap 可以获取到一个 Set

4
Java集合中的任何Set实际上都包含用于存储的Map。 - mart
5
为什么没有专门针对这种东西的课程呢? - Stan Kurilin
14
Java.util的维护者可能想停止为所有内容提供双重Map和Set版本,选择只提供newSetFromMap(),这很容易想象...不是吗? - Kevin Bourrillion
24
值得注意的是,在 Android API 9 之前,Collections#newSetFromMap 方法在 Android 中不存在。不过,可以很容易地找到实现并编译到您的应用程序中,但这会导致兼容性问题。 - nmr
4
JavaDoc是正确的。注意,这个答案中的代码返回一个包含对象而不是布尔值的Set。newSetFromMap方法创建的是键的类型对应的Set,而不是值的类型。 - kabuko
显示剩余10条评论

3

如果有人想要优化内存使用,性能比guava弱引用interners要好得多。https://docs.geotools.org/stable/javadocs/org/geotools/util/CanonicalSet.html。 - elbo

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