WeakHashMap in Java with example
WeakHashMap in java is an implementation of Map interface.
Reference in java are memory address where the created objects points in the memory. In a WeakHashMap, concept of Weak Reference is used.
As soon as you create an object in java and assign it to some variable, it becomes strongly reachable.
Weak reference object can somewhat be similar to object that has no memory references i.e. it can be garbage collected now.
Difference between WeakHashMap vs HashMap
In other Map implementations like a HashMap, the keys are strongly reachable. For example, if a HashMap has keys as Person class as shown below and if Person object is set to null, even after this if we will do map.get(Person) we will get the value from the memory since the keys are strongly referenced in a HashMap.
wm.put(person, person.getFirstName());
person = null;
System.gc();
System.out.println("Hash Map :" + wm.toString());
Output : Hash Map :{test.Person@12dacd1=John}
Compared to HashMap, WeakHashMap is the one which will remove its enteries as soon as the keys have no reference in the memory. For example, if a WeakHashMap has keys as Person class as shown below and if Person object is set to null, now if you do map.get(Person) we will get null out of it because the key has no reference (or rather weakly reachable).
wm.put(person, person.getFirstName());
person = null;
System.gc();
System.out.println("Weak Hash Map :" + wm.toString());
Output : Weak Hash Map :{}
Map<Person, String> wm = new WeakHashMap<Person, String>();
Person person = new Person();
person.setAge(25);
person.setFirstName("John");
wm.put(person, person.getFirstName());
Person person2 = new Person();
person2.setAge(35);
person2.setFirstName("Anderson");
wm.put(person2, person2.getFirstName());
System.gc();
System.out.println("Weak Hash Map :" + wm.toString());
person = null;
System.gc();
System.out.println("Weak Hash Map :" + wm.toString());
Running the above code gives us
Weak Hash Map :{test.Person@42719c=Anderson, test.Person@10385c1=John}
Weak Hash Map :{test.Person@42719c=Anderson}
Before nullifying the person object, WeakHashMap consists of both the enteries. Once the person object is nullified, garbage collector removed the object from the memory and since it is weakly referenced, WeakHashMap removed the entry for key person
String as a key for WeakHashMap
String is not suitable for WeakHashMap if used as a key. This is because, when a String object is created JVM creates the object in the String pool also. They may remain strongly referenced in the string pool even after you have nullified the reference.
Map<String, String> stringWeakHashMap = new WeakHashMap<String, String>();
String str1 = "Key 1";
String str2 = "Key 2";
stringWeakHashMap.put(str1, "Value 1");
stringWeakHashMap.put(str2, "Value 2");
str1 = null;
System.gc();
System.out.println("Weak Hash Map :" + stringWeakHashMap.toString());
After running the above code the output generated is
Weak Hash Map :{Key 2=Value 2, Key 1=Value 1}
It is clearly visible, since the string objects have strong reference due to string pool the key "str1" is not removed from the WeakHashMap
Nice article.
ReplyDeleteBut we can still use String[s] as keys in WeakHashMap.
Try this code snippet.
Code Snippet #1
String k1 = "key1";
String k2 = "key2";
Map map2 = new WeakHashMap();
String key1 = new String(k1);
String key2 = new String(k2);
map2.put(key1, p1);
map2.put(key2, p2);
System.out.println(map2);
key2 = null;
System.gc();
System.out.println(map2);
output :
{key1=com.test.java.Person@677327b6, key2=com.test.java.Person@14ae5a5}
{key1=com.test.java.Person@677327b6}
Code Snippet #2
Map map2 = new WeakHashMap();
String key1 = new String("key1");
String key2 = new String("key2");
map2.put(key1, p1);
map2.put(key2, p2);
System.out.println(map2);
key2 = null;
System.gc();
System.out.println(map2);
Output #2 :
{key1=com.test.java.Person@677327b6, key2=com.test.java.Person@14ae5a5}
{key1=com.test.java.Person@677327b6}
Clearly, GC is removing the String objects which do not have any strong reference.