0

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

4

3 回答 3

8

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

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

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

于 2012-12-20T20:29:51.043 回答
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垃圾收集器可以很好地处理循环对象引用。

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

于 2012-12-20T21:16:13.730 回答
0

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

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"
于 2012-12-20T21:08:35.353 回答