Java WeakHashMap Tutorial with Examples
1. WeakHashMap
WeakHashMap is a class similar to HashMap class, which all use hashing technique to store and retrieve data. The difference is that if an object is specified as a key of WeakHashMap, it can be removed from memory by Garbage Collector (GC) if it is no longer being used somewhere else stronger than GC. Once the key is removed by GC, the corresponding mapping is also removed from WeakHashMap.
In common sense, if an object is in use somewhere, it is useful and cannot be removed from memory. However, WeakHashMap is specially designed and is considered weaker than GC, an object whose key can still be removed from memory.
public class WeakHashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>
AnyObject class will participate in the examples in this article:
AnyObject.java
package org.o7planning.beans;
public class AnyObject {
private String s;
public AnyObject(String s) {
this.s = s;
}
public String getS() {
return s;
}
}
First, let's see the example below, then we'll analyze what happened:
WeakHashMap_objectKey_ex1.java
package org.o7planning.weakhashmap.ex;
import java.util.WeakHashMap;
import org.o7planning.beans.AnyObject;
public class WeakHashMap_objectKey_ex1 {
public static void main(String[] args) throws InterruptedException {
// (1) Create a reference objK1 points to AnyObject("S1") object.
AnyObject objK1 = new AnyObject("S1");
AnyObject objK2 = new AnyObject("S2");
// Create WeakHashMap object:
WeakHashMap<AnyObject,Integer> map = new WeakHashMap<AnyObject,Integer>();
map.put(objK1, 1000);
map.put(objK2, 2000);
System.out.println(map);
// (2) Set reference objK1 to null.
objK1 = null;
// Garbage Collector is called
System.gc();
System.out.println("\n --- After Garbage Collector is called: --- \n");
Thread.sleep(3000);
System.out.println(map);
}
}
Output:
{org.o7planning.beans.AnyObject@1c4af82c=2000, org.o7planning.beans.AnyObject@5e91993f=1000}
--- After Garbage Collector is called: ---
{org.o7planning.beans.AnyObject@1c4af82c=2000}
(1) - First, objK1 reference is created and pointed to AnyObject("S1") object, which is a key of WeakHashMap.
(2) -ObjK1 reference is pointing to a null value. At this time, there are no longer any strong references that point to AnyObject("S1") object. Although it is being used as a key of WeakHashMap, it is still considered eligible to be removed by Garbage Collector. Since GC is considered stronger than WeakHashMap.
Garbage Collector
Java's Garbage Collector works automatically to remove unused objects from memory. You can actively call it with System.gc() method, but there is no guarantee that it will be effective immediately.
- Java Garbage Collector
Modifying the above example, if we replace WeakHashMap by HashMap, AnyObject("S1") object will not be removed by Garbage Collector. Because HashMap is considered stronger than Garbage Collector.
HashMap_objectKey_ex1.java
package org.o7planning.weakhashmap.ex;
import java.util.HashMap;
import org.o7planning.beans.AnyObject;
public class HashMap_objectKey_ex1 {
public static void main(String[] args) throws InterruptedException {
// (1) Create a reference objK1 points to AnyObject("S1") object.
AnyObject objK1 = new AnyObject("S1");
AnyObject objK2 = new AnyObject("S2");
// Create HashMap object:
HashMap<AnyObject,Integer> map = new HashMap<AnyObject,Integer>();
map.put(objK1, 1000);
map.put(objK2, 2000);
System.out.println(map);
// (2) Set reference objK1 to null.
objK1 = null;
// Garbage Collector is called
System.gc();
System.out.println("\n --- After Garbage Collector is called: --- \n");
Thread.sleep(3000);
System.out.println(map);
}
}
Output:
{org.o7planning.beans.AnyObject@1c4af82c=2000, org.o7planning.beans.AnyObject@5e91993f=1000}
--- After Garbage Collector is called: ---
{org.o7planning.beans.AnyObject@1c4af82c=2000, org.o7planning.beans.AnyObject@5e91993f=1000}
- HashMap
- LinkedHashMap
- TreeMap
- IdentityHashMap
- EnumMap
- ConcurrentSkipListMap
- ConcurrentHashMap
In this article we will discuss the different key types of WeakHashMap and how GC treats them.
No | Key Type | Example |
1 | Primitive | Integer aKey = 3;
String aKey = "aString"; |
2 | Object | newAnyObject();
newString("aString"); newInteger(3); |
2. Primitive Keys
Objects created from primitive values that do not use "new" operator will not be removed by GC if it is being used as a key of a WeakHashMap.
Primitive Keys
Integer key1 = 1000;
Double key2 = 2000.2;
String key3 = "SomeKey";
WeakHashMap_primitiveKey_ex1.java
package org.o7planning.weakhashmap.ex;
import java.util.WeakHashMap;
public class WeakHashMap_primitiveKey_ex1 {
public static void main(String[] args) throws InterruptedException {
// (1) Create a reference objK1 points to a primitive value.
Integer objK1 = 100;
Integer objK2 = 200;
// Create WeakHashMap object:
WeakHashMap<Integer, String> map = new WeakHashMap<Integer, String>();
map.put(objK1, "One Hundred");
map.put(objK2, "Two Hundred");
System.out.println(map);
// (2) Set reference objK1 to null.
objK1 = null;
// Garbage Collector is called
System.gc();
System.out.println("\n --- After Garbage Collector is called: --- \n");
Thread.sleep(5000);
System.out.println(map);
}
}
Output:
{200=Two Hundred, 100=One Hundred}
--- After Garbage Collector is called: ---
{200=Two Hundred, 100=One Hundred}
3. Object Keys
Objects created with "new" operator will be removed from memory by GC if there is no strong reference that point to it, even if it is being used as a key of the WeakHashMap. As mentioned above, GC is considered stronger than WeakHashMap.
Object Keys
AnyObject objK1 = new AnyObject("S1");
String objK2 = new String("S2");
Integer objK3 = new Integer(1000);
String objK4 = new String("S4");
Example:
WeakHashMap_objectKey_ex2.java
package org.o7planning.weakhashmap.ex;
import java.util.WeakHashMap;
import org.o7planning.beans.AnyObject;
public class WeakHashMap_objectKey_ex2 {
public static void main(String[] args) throws InterruptedException {
// (1) Create a reference objK1 points to String object.
AnyObject objK1 = new AnyObject("S1");
String objK2 = new String("S2");
Integer objK3 = new Integer(1000);
String objK4 = new String("S4");
// Create WeakHashMap object:
WeakHashMap<Object,Integer> map = new WeakHashMap<Object,Integer>();
map.put(objK1, 1000);
map.put(objK2, 2000);
map.put(objK3, 3000);
map.put(objK4, 4000);
System.out.println(map);
// (2) Set references objK1, objK2, objK3 to null.
objK1 = null;
objK2 = null;
objK3 = null;
// Garbage Collector is called
System.gc();
System.out.println("\n --- After Garbage Collector is called: --- \n");
Thread.sleep(3000);
System.out.println(map);
}
}
Output:
{S2=2000, org.o7planning.beans.AnyObject@5e91993f=1000, S4=4000, 1000=3000}
--- After Garbage Collector is called: ---
{S4=4000}
Objects created by "new" operator will be removed from memory by GC if the program needs more memory and if there are no strong references pointing to it. In this case you do not need to actively call the System.gc() method.
In the example below we try to fill the memory by creating lots of objects continuously.
WeakHashMap_objectKey_ex3.java
package org.o7planning.weakhashmap.ex;
import java.util.WeakHashMap;
import org.o7planning.beans.AnyObject;
public class WeakHashMap_objectKey_ex3 {
public static void main(String[] args) throws InterruptedException {
// (1) Create a reference objK1 points to String object.
AnyObject objK1 = new AnyObject("S1");
String objK2 = new String("S2");
Integer objK3 = new Integer(1000);
String objK4 = new String("S4");
String objK5 = "S5"; // Primitive Key
// Create WeakHashMap object:
WeakHashMap<Object,Integer> map = new WeakHashMap<Object,Integer>();
map.put(objK1, 1000);
map.put(objK2, 2000);
map.put(objK3, 3000);
map.put(objK4, 4000);
map.put(objK5, 5000);
int ORIGIN_MAP_SIZE = map.size();
System.out.println(map);
int i = 0;
while(true) {
if(map.size() < ORIGIN_MAP_SIZE) {
System.out.println("WeakHashMap Size: " + map.size());
System.out.println(map);
break;
}
i++;
// (2) Make the memory full by creating lots of Strings
String s = new String("String" + i);
System.out.println("Create new String: " + s);
System.out.println(" >>> Now WeakHashMap size is: " + map.size());
}
}
}
Output:
{S2=2000, org.o7planning.beans.AnyObject@5e91993f=1000, S5=5000, S4=4000, 1000=3000}
Create new String: String1
....
Create new String: String347615
>>> Now WeakHashMap size is: 5
Create new String: String347616
>>> Now WeakHashMap size is: 5
Create new String: String347617
>>> Now WeakHashMap size is: 5
WeakHashMap Size: 1
{S5=5000}
4. Why do we need WeakHashMap?
Basically, WeakHashMap is a solution to save memory, which is useful if you need a Map object to store mappings for the keys you know at a time. Keys that are no longer needed are automatically removed by GC.
Beside though characteristics mentioned above, WeakHashMap has all the characteristics of a regular Map. You can see more how to use Map in the article below:
See more:
Java Collections Framework Tutorials
- Java PriorityBlockingQueue Tutorial with Examples
- Java Collections Framework Tutorial with Examples
- Java SortedSet Tutorial with Examples
- Java List Tutorial with Examples
- Java Iterator Tutorial with Examples
- Java NavigableSet Tutorial with Examples
- Java ListIterator Tutorial with Examples
- Java ArrayList Tutorial with Examples
- Java CopyOnWriteArrayList Tutorial with Examples
- Java LinkedList Tutorial with Examples
- Java Set Tutorial with Examples
- Java TreeSet Tutorial with Examples
- Java CopyOnWriteArraySet Tutorial with Examples
- Java Queue Tutorial with Examples
- Java Deque Tutorial with Examples
- Java IdentityHashMap Tutorial with Examples
- Java WeakHashMap Tutorial with Examples
- Java Map Tutorial with Examples
- Java SortedMap Tutorial with Examples
- Java NavigableMap Tutorial with Examples
- Java HashMap Tutorial with Examples
- Java TreeMap Tutorial with Examples
- Java PriorityQueue Tutorial with Examples
- Java BlockingQueue Tutorial with Examples
- Java ArrayBlockingQueue Tutorial with Examples
- Java TransferQueue Tutorial with Examples
Show More