WeakHashMap in Java with Real-World Example

WeakHashMap is a specialized implementation of the Map interface from the java.util package where keys are stored as weak references. If a key is not referred to outside of the WeakHashMap, it can be garbage collected, and its entry is removed from the map.

Key Points: 

Weak References: The keys in a WeakHashMap are held weakly, meaning that if the only reference to a key is from the WeakHashMap, it can be garbage collected. 

Use Case: Ideal for caches where you want entries to be removed once they are no longer referenced elsewhere. 

Not Thread-Safe: WeakHashMap itself is not thread-safe. External synchronization is necessary if it's accessed by multiple threads concurrently. 

Nulls: Both null keys and null values are supported.

Java WeakHashMap Common Methods

import java.util.WeakHashMap;

public class WeakHashMapExample {

    public static void main(String[] args) {
        // 1. Create a `WeakHashMap`
        WeakHashMap<String, String> weakMap = new WeakHashMap<>();

        // 2. Add entries to the `WeakHashMap`
        weakMap.put("One", "First");
        weakMap.put("Two", "Second");
        weakMap.put("Three", "Third");
        System.out.println("2. WeakHashMap content: " + weakMap);

        // 3. Check if a key is present
        boolean hasKeyTwo = weakMap.containsKey("Two");
        System.out.println("3. Contains key 'Two'? " + hasKeyTwo);

        // 4. Get a value using its key
        String valueOfThree = weakMap.get("Three");
        System.out.println("4. Value for key 'Three': " + valueOfThree);

        // 5. Remove an entry using its key
        weakMap.remove("Two");
        System.out.println("5. WeakHashMap after removing key 'Two': " + weakMap);

        // 6. Check the size of the WeakHashMap
        int size = weakMap.size();
        System.out.println("6. Size of the WeakHashMap: " + size);
    }
}

Output:

2. WeakHashMap content: {One=First, Two=Second, Three=Third}
3. Contains key 'Two'? true
4. Value for key 'Three': Third
5. WeakHashMap after removing key 'Two': {One=First, Three=Third}
6. Size of the WeakHashMap: 2

Explanation:

1. Initialized a WeakHashMap named weakMap.

2. Added key-value pairs using the put() method.

3. Checked the presence of a specific key with the containsKey() method.

4. Retrieved the value associated with a particular key using the get() method.

5. Removed a key-value pair using the remove() method.

6. Checked the number of key-value pairs using the size() method.

WeakHashMap is similar to HashMap with a key difference: in WeakHashMap, the keys are held weakly, which means if a WeakHashMap key is not referenced outside, it becomes eligible for garbage collection.

Real-World Use Case: Java WeakHashMap in Cache Implementation

import java.util.WeakHashMap;

public class CacheSystem {

    // Define a simple cache using `WeakHashMap`
    private final WeakHashMap<Object, String> cache = new WeakHashMap<>();

    // Method to add item to cache
    public void addToCache(Object key, String value) {
        cache.put(key, value);
    }

    // Method to get item from cache
    public String getFromCache(Object key) {
        return cache.getOrDefault(key, "Not Found");
    }

    public static void main(String[] args) throws InterruptedException {
        CacheSystem cacheSystem = new CacheSystem();

        // 1. Adding entries to the cache
        Object obj1 = new Object();
        Object obj2 = new Object();

        cacheSystem.addToCache(obj1, "Data for obj1");
        cacheSystem.addToCache(obj2, "Data for obj2");
        System.out.println("1. Cache after adding entries: " + cacheSystem.cache);

        // 2. Nullifying reference and invoking garbage collector
        obj1 = null;
        System.gc();
        Thread.sleep(500);  // giving some time for garbage collector to work

        System.out.println("2. Cache after nullifying a reference and calling GC: " + cacheSystem.cache);
    }
}

Output:

1. Cache after adding entries: {java.lang.Object@XYZ=Data for obj1, java.lang.Object@ABC=Data for obj2}
2. Cache after nullifying a reference and calling GC: {java.lang.Object@ABC=Data for obj2}
(Note: Object hash codes XYZ and ABC will be different for each run)

Explanation:

1. Initialized a simple cache system using WeakHashMap where the keys represent the objects we want to keep track of, and values are the associated cached data.

2. Added two objects (obj1 and obj2) and their corresponding data to the cache.

3. To simulate cache eviction, we nullified the reference of obj1 and invoked the garbage collector. Since WeakHashMap does not prevent its keys from being garbage collected, after garbage collection, the entry corresponding to the nullified reference (obj1) gets removed automatically.

The primary use case of WeakHashMap is to build cache systems where you don't want the cache to prevent its keys from being garbage collected. If a key is no longer in use or referenced outside of the WeakHashMap, it can be garbage collected, thus not causing memory leaks in caching scenarios.

Comments