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<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 引用的,所以当上面HashMap
中的emp
(可变键)通过附加一个字符串来更改时,就像emp.append("changed")
一样,它会反映在HashMap
中。WeakHashMap
也是如此(如果更改/更新可变键,则会反映更改)。这意味着该密钥是从WeakHashMap引用的。
谁能解释一下WeakHashMap
实现的不同之处,即密钥可以通过引用进行垃圾回收?
谢谢。
emp = new StringBuilder("sss");
不会影响HashMap
中已有的条目(由语句 new StringBuilder("Stack");
创建的条目),因为HashMap
包含自己对最初由 emp
引用的StringBuilder
实例的引用。它不会创建StringBuilder
实例的副本,只会保留引用的副本。
另一方面,对于 WeakHashMap
,WeakHashMap
中存在密钥不会阻止它被垃圾回收,因此如果没有其他引用您放入映射中的密钥,GC 可以释放该实例。因此,将新实例分配给 emp1
后,只有映射包含对它引用的原始实例的引用,GC 可以释放它。
以下是相关的Javadoc参考:
当弱哈希图中的条目不再正常使用时,其密钥将自动删除。更准确地说,给定键的映射的存在不会阻止垃圾回收器丢弃该键
编辑:
至于WeakHashMap
的实现有何不同,WeakHashMap
的Entry
扩展WeakReference<Object>
,这是一个引用另一个实例(在本例中为条目的键)的实例,并且不妨碍其引用被 GC 释放。