【问题标题】:How HashMap handles the updated <key,value>,if value itself is a Hashmap?如果 value 本身是 Hashmap,HashMap 如何处理更新的 <key,value>?
【发布时间】:2012-12-08 10:22:58
【问题描述】:

当我们将 &lt;key,value&gt; 放入 HashMap 时,如果键已存在于 HashMap 中,则值将被替换。但是如果一个键的值本身就是一个 HashMap,那么它会被 HashMap 替换吗?

【问题讨论】:

  • “什么”?您能否显示一些示例代码或更详细地解释此“错误”?从标签来看,这听起来像是一个“循环引用”(这在 JVM 中不是一个问题,因为它们会正确地 GC 任何不是强可达的对象);然而,有问题的对象可能总是强可达,因此永远不可回收..
  • 没有什么特别的事情发生。
  • 只有当两个 HashMap(键)相等时,第一个值才会被替换。否则,您将在地图中有两个不同的条目。

标签: java memory-leaks jvm out-of-memory


【解决方案1】:

如果我理解您的问题,您想知道您刚才所说的是否会导致内存泄漏(如果这不是您要问的,请更新您的问题)。

如果你这样做:

Map<?, ?> m = new HashMap<Object, Object>();
m.put(m, m);

那么m 最终将只包含对其自身的引用。由于 Java 的 GC 如何通过对象引用图工作,并且因为它们使用在 GC 扫描期间跟踪访问过的节点的算法,如果没有维护对 m 的引用,那么 m 将被垃圾收集,尽管包含引用对自己。循环引用在 Java GC 中得到了完美的处理。

如果将m 放入字段(即,不是在方法中声明的局部变量),那就另当别论了。

  • 如果m 被放置在static 字段中,那么总会有来自GC 根的引用,这意味着它不会被回收。注意:static 字段中强烈引用的任何内容都不会被垃圾回收。
  • 如果将m 放置在成员字段(非static)中,则在包含它的对象被垃圾回收之前,地图不会被垃圾回收。
  • 如果有多个字段引用 m,则 m 不会被垃圾回收,直到 所有这些引用是 a) 可以被垃圾回收的对象的一部分或b) 设置为 null 或其他值以不再引用 m

TL;DR垃圾收集器可以很好地处理循环对象引用。

旁注:请用信息更新您的问题,不要只是将其作为 cmets 添加到您的问题或其他人的答案中。

【讨论】:

【解决方案2】:

您问题中的措辞有点不透明,但HashMap&lt;HashMap, Object&gt; 是完全有效的(如果有点奇怪)。在这种情况下,如果:

HashMap map = new HashMap<HashMap<String, String>, String>();
HashMap a = new HashMap<String, String>();
HashMap b = new HashMap<String, String>();  //a.equals(b) == true

map.put(a, "foo");  //map.get(a) would now return "foo"
map.put(b, "bar");  //original entry is replaced, map.get(a) would now return "bar"

【讨论】:

    【解决方案3】:

    是的,它将被替换。请记住,地图只存储对其他对象的引用。

    你把一个 HashMap 的引用放到一个 map 中,这个 map 会保存一个对这个 HashMap 的引用。

    如果您使用相同的键放置对另一个 HashMap 的引用,则对第一个放置的 HashMap 的引用将替换为对新 HashMap 的引用。对象的类型无关紧要。它总是以同样的方式工作。

    【讨论】:

    • 私有静态映射 m =new HashMap;是类值的实例变量,键是接口。在 Synchronized(m){m.put(this,this);} 中,正在填充值。场景是 HashMap 已经有 63 个元素的 HashMap 条目作为键的值,现在这个键的值是 64 个元素的 Hashmap 条目,根据我的说法,这个键现在应该只有 64 个 HashMap 条目但是两者我通过 Eclipse MAT 分析的 Heap 中存在 63 个条目和 64 个条目。
    • 使用真实代码编辑您的问题。但是m.put(this, this),其中this 是一个可变的HashMap,显然会引起问题。键应该是不可变的。如果它们的 hashhCode 在存储在 HashMap 中时发生变化,则 HashMap 将无法正常工作。
    • 非常感谢您的解释。我强烈怀疑这是我的应用程序内存泄漏的原因。请解释一下,如何纠正这个可变键,我应该改变什么来纠正我的 HashMap?再次感谢您
    • 我只能纠正我看到的代码。您还没有向我们展示您的代码。
    • 我不打算在这里粘贴代码,因为这将成为一个完整性问题,他们会将我赶出这个组织。我尝试了一种解决方法,我从地图中删除了静态,并将 hashCode 更改为常量。现在它可以正常工作了。
    猜你喜欢
    • 2011-05-19
    • 1970-01-01
    • 1970-01-01
    • 2019-01-30
    • 1970-01-01
    • 2012-06-09
    • 2012-06-30
    • 1970-01-01
    • 2018-10-30
    相关资源
    最近更新 更多