HashMap - 更改键值

时间:2016-03-09 13:49:50

标签: java weak-references

HashMap<StringBuilder, StringBuilder> aMap = new 
       HashMap<StringBuilder, StringBuilder>();

StringBuilder emp = new StringBuilder("Stack");
StringBuilder val = new StringBuilder("Programmer");

aMap.put(emp, val);
emp = new StringBuilder("sss");
System.out.println(aMap);`

虽然emp值是chnaged,但它不会反映在HashMap中。是因为HashMap在放置新值时会使用某种复制构造函数吗?

现在来到WeakHashMap:

WeakHashMap<StringBuilder, StringBuilder> aMap1 = 
            new WeakHashMap<StringBuilder, StringBuilder>();
    StringBuilder emp1 = new StringBuilder("WeakStack");
    StringBuilder val1 = new StringBuilder("Programmer");
aMap1.put(emp1, val1);
emp1 = new StringBuilder("WeakStack1");

在一些GC调用之后,aMap1变为空。为什么这样?是因为指向的键不再存在了吗?

更新:我从答案中了解到密钥是从HashMap引用的,所以当上面emp中的HashMap(可变密钥)通过向其附加字符串来更改时,就像emp.append("changed")一样,它反映在HashMapWeakHashMap也是如此(如果更改/更新了可变密钥,则会反映更改)。这意味着该密钥是从WeakHashMap引用的。

有人可以解释一下WeakHashMap实现的不同之处,即密钥可以被垃圾收集但是被引用了吗?

感谢。

2 个答案:

答案 0 :(得分:2)

由于emp = new StringBuilder("sss");,{p> HashMap不会影响new StringBuilder("Stack");(由语句HashMap创建的条目)中已有的条目包含自己对StringBuilder实例的引用,该实例最初由emp引用。它不会创建StringBuilder实例的副本,它只保留引用的副本。

另一方面,对于WeakHashMapWeakHashMap中存在密钥并不会阻止它被垃圾回收,因此如果没有其他对密钥的引用,放入地图后,GC可以释放该实例。因此,在为emp1分配新实例后,只有映射包含对其引用的原始实例的引用,GC才能释放它。

这里是相关的Javadoc参考:

  

当WeakHashMap中的条目不再正常使用时,它将自动被删除。更准确地说,给定密钥的映射的存在不会阻止密钥被垃圾收集器丢弃

编辑:

至于WeakHashMap的实现方式有何不同,Entry的{​​{1}}扩展WeakHashMap,这是一个引用另一个实例的实例(在这种情况下的条目)并且不会阻止它的指示物被GC释放。

答案 1 :(得分:0)

对于第一个问题,你可以像打印机一样看待它。您可以在某个程序中创建图像并将其打印在一张纸上。现在您更改了程序中的图像,但不打印出来。 2张图片不同。为什么?因为您没有打印出更改。

同样适用于HashMap。您创建了Object并将其放入地图中。您再次更改了Object,但在HashMap中没有更改。为什么?很简单,因为你没有应用这些变化。