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引用的,因此,通过在其上附加一个字符串(如emp)来更改上述HashMap中的emp.append("changed")(可变键)时,它会反映在HashMap中。 WeakHashMap也是如此(如果更改/更新了可变键,则会反映出更改)。这意味着正在从WeakHashMap引用该密钥。

谁能解释WeakHashMap实现的不同之处,即尽管引用了密钥也可以对其进行垃圾回收?

谢谢。

最佳答案

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

另一方面,使用StringBuilder时,WeakHashMap中存在键不会阻止对其进行垃圾回收,因此,如果没有其他引用,则您可以将GC释放到映射中该实例。因此,在为WeakHashMap分配新实例后,只有映射包含对它引用的原始实例的引用,并且GC可以释放它。

这是相关的Javadoc参考:


  当WeakHashMap中的项不再是普通使用时,将自动删除该项。更确切地说,给定键的映射的存在不会阻止该键被垃圾收集器丢弃


编辑:

关于emp1的实现方式有何不同,WeakHashMapEntry扩展了WeakHashMap,这是一个实例,它引用另一个实例(在此例中为条目的键)并且不会阻止GC释放其参考对象。

关于java - HashMap-更改键值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35893458/

10-09 15:47