HashMap - 更改键值
HashMap - Changing key value
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
值被改变了,但它没有反映在 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 引用的,因此当上面 HashMap
中的 emp
(可变键)通过向其附加字符串来更改时,例如 emp.append("changed")
,反映在HashMap
。 WeakHashMap
也是如此(如果可变键是 changed/updated,则反映更改)。这意味着该键是从 WeakHashMap 引用的。
任何人都可以解释一下 WeakHashMap
实施方式的不同之处在于,虽然密钥被引用但可以被垃圾收集?
谢谢。
emp = new StringBuilder("sss");
不会影响 HashMap
中已有的条目(由语句 new StringBuilder("Stack");
创建的条目),因为 HashMap
包含自己的引用到最初由 emp
引用的 StringBuilder
实例。它不会创建 StringBuilder
实例的副本,它只会保留引用的副本。
另一方面,对于 WeakHashMap
,WeakHashMap
中存在一个键并不能阻止它被垃圾回收,所以如果没有其他引用该键,你放入地图,GC 可以释放该实例。因此,当你为emp1
分配一个新实例后,只有map包含了对它引用的原始实例的引用,GC才能释放它。
这是相关的 Javadoc 参考资料:
An entry in a WeakHashMap will automatically be removed when its key is no longer in ordinary use. More precisely, the presence of a mapping for a given key will not prevent the key from being discarded by the garbage collector
编辑:
至于WeakHashMap
的实现有何不同,WeakHashMap
的Entry
扩展了WeakReference<Object>
,是一个实例引用另一个实例(在这种情况下是条目的键)并且不会阻止 GC 释放其所指对象。
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
值被改变了,但它没有反映在 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 引用的,因此当上面 HashMap
中的 emp
(可变键)通过向其附加字符串来更改时,例如 emp.append("changed")
,反映在HashMap
。 WeakHashMap
也是如此(如果可变键是 changed/updated,则反映更改)。这意味着该键是从 WeakHashMap 引用的。
任何人都可以解释一下 WeakHashMap
实施方式的不同之处在于,虽然密钥被引用但可以被垃圾收集?
谢谢。
emp = new StringBuilder("sss");
不会影响 HashMap
中已有的条目(由语句 new StringBuilder("Stack");
创建的条目),因为 HashMap
包含自己的引用到最初由 emp
引用的 StringBuilder
实例。它不会创建 StringBuilder
实例的副本,它只会保留引用的副本。
另一方面,对于 WeakHashMap
,WeakHashMap
中存在一个键并不能阻止它被垃圾回收,所以如果没有其他引用该键,你放入地图,GC 可以释放该实例。因此,当你为emp1
分配一个新实例后,只有map包含了对它引用的原始实例的引用,GC才能释放它。
这是相关的 Javadoc 参考资料:
An entry in a WeakHashMap will automatically be removed when its key is no longer in ordinary use. More precisely, the presence of a mapping for a given key will not prevent the key from being discarded by the garbage collector
编辑:
至于WeakHashMap
的实现有何不同,WeakHashMap
的Entry
扩展了WeakReference<Object>
,是一个实例引用另一个实例(在这种情况下是条目的键)并且不会阻止 GC 释放其所指对象。