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")
一样,它反映在HashMap
。 WeakHashMap
也是如此(如果更改/更新了可变密钥,则会反映更改)。这意味着该密钥是从WeakHashMap引用的。
有人可以解释一下WeakHashMap
实现的不同之处,即密钥可以被垃圾收集但是被引用了吗?
感谢。
答案 0 :(得分:2)
emp = new StringBuilder("sss");
,{p> HashMap
不会影响new StringBuilder("Stack");
(由语句HashMap
创建的条目)中已有的条目包含自己对StringBuilder
实例的引用,该实例最初由emp
引用。它不会创建StringBuilder
实例的副本,它只保留引用的副本。
另一方面,对于WeakHashMap
,WeakHashMap
中存在密钥并不会阻止它被垃圾回收,因此如果没有其他对密钥的引用,放入地图后,GC可以释放该实例。因此,在为emp1
分配新实例后,只有映射包含对其引用的原始实例的引用,GC才能释放它。
这里是相关的Javadoc参考:
当WeakHashMap中的条目不再正常使用时,它将自动被删除。更准确地说,给定密钥的映射的存在不会阻止密钥被垃圾收集器丢弃
编辑:
至于WeakHashMap
的实现方式有何不同,Entry
的{{1}}扩展WeakHashMap
,这是一个引用另一个实例的实例(在这种情况下的条目)并且不会阻止它的指示物被GC释放。
答案 1 :(得分:0)
对于第一个问题,你可以像打印机一样看待它。您可以在某个程序中创建图像并将其打印在一张纸上。现在您更改了程序中的图像,但不打印出来。 2张图片不同。为什么?因为您没有打印出更改。
同样适用于HashMap
。您创建了Object
并将其放入地图中。您再次更改了Object
,但在HashMap
中没有更改。为什么?很简单,因为你没有应用这些变化。