Search code examples
javaweak-references

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);`

Though emp value is chnaged, it does not reflect in a HashMap. Is it because HashMap uses some kind of copy constructor while putting a new value?

Now coming to 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");

After some GC calls, the aMap1 becomes empty. Why so? Is it because the key pointing to doesnot exist anymore?

Update : I understand from the answers that key is referenced from HashMap, so when emp(mutable key) in above HashMap is changed by appending a String to it, like emp.append("changed"), it reflects in HashMap. Same is true for WeakHashMap(if a mutable key is changed/updated, the change is reflected). Which means that key is being referenced from WeakHashMap.

Could anyone please explain what is WeakHashMap implementation different that the key can be garbage collected though its being referenced?

Thanks.


Solution

  • emp = new StringBuilder("sss"); doesn't affect the entry that's already in the HashMap (the one created by the statement new StringBuilder("Stack");), since the HashMap contains its own reference to the StringBuilder instance that was originally referred by emp. It doesn't create a copy of the StringBuilder instance, it only keeps a copy of the reference.

    On the other hand, with WeakHashMap, the presence of a key in the WeakHashMap doesn't prevent it from being garbage collected, so if there is no other reference to the key you put in the map, the GC can release that instance. Therefore, after you assign a new instance to emp1, only the map contains a reference to the original instance it referred to, and the GC can release it.

    Here's the relevant Javadoc reference :

    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

    EDIT :

    As for how the implementation of WeakHashMap is different, the Entry of a WeakHashMap extends WeakReference<Object>, which is an instance that refers to another instance (the key of the entry in this case) and doesn't prevent its referent from being released by the GC.