Java WeakHashMap Example

In this tutorial, we will explore the WeakHashMap class in Java, which is a specialized implementation of the Map interface. Unlike the standard HashMap, WeakHashMap uses weak references for its keys, which means that entries will be automatically removed when their keys are no longer in use. This can help prevent memory leaks in certain scenarios. This tutorial will demonstrate how to use WeakHashMap with examples, using the latest Java version to ensure modern practices and features.

Table of Contents

  1. Introduction
  2. Prerequisites
  3. Step-by-Step Guide
    1. Creating a WeakHashMap
    2. Adding and Retrieving Elements
    3. Understanding Garbage Collection with WeakHashMap
    4. Comparing WeakHashMap with HashMap
  4. Complete Code Example
  5. Conclusion

Introduction

WeakHashMap is a special type of Map that uses weak references for keys. This means that if a key is no longer in ordinary use (not referenced elsewhere), the entry will be eligible for garbage collection and will be removed from the map. WeakHashMap can be useful in scenarios where memory-sensitive caching is required.

Prerequisites

Before we start, ensure you have the following:

  • Java Development Kit (JDK) installed (latest version preferred)
  • An Integrated Development Environment (IDE) such as IntelliJ IDEA or Eclipse

Step-by-Step Guide

Step 1: Creating a WeakHashMap

First, let's create a WeakHashMap and add some key-value pairs to it.

import java.util.Map;
import java.util.WeakHashMap;

public class WeakHashMapExample {
    public static void main(String[] args) {
        // Create a WeakHashMap
        Map<String, Integer> weakMap = new WeakHashMap<>();

        // Add key-value pairs to the map
        weakMap.put("Ravi", 25);
        weakMap.put("Sita", 30);
        weakMap.put("Arjun", 22);
        weakMap.put("Lakshmi", 20);

        // Print the map
        System.out.println("WeakHashMap: " + weakMap);
    }
}

Step 2: Adding and Retrieving Elements

Let's add some elements to the WeakHashMap and retrieve values using different keys.

public class WeakHashMapExample {
    public static void main(String[] args) {
        // Create a WeakHashMap
        Map<String, Integer> weakMap = new WeakHashMap<>();

        // Add key-value pairs to the map
        weakMap.put("Ravi", 25);
        weakMap.put("Sita", 30);
        weakMap.put("Arjun", 22);
        weakMap.put("Lakshmi", 20);

        // Retrieve and print values using different keys
        System.out.println("Ravi: " + weakMap.get("Ravi"));
        System.out.println("Sita: " + weakMap.get("Sita"));
    }
}

Output:

Ravi: 25
Sita: 30

Step 3: Understanding Garbage Collection with WeakHashMap

To understand the behavior of WeakHashMap with garbage collection, we need to use keys that are not strongly referenced elsewhere. Let's create some key objects, add them to the WeakHashMap, and then invoke garbage collection to observe the behavior.

public class WeakHashMapExample {
    public static void main(String[] args) throws InterruptedException {
        // Create a WeakHashMap
        Map<String, Integer> weakMap = new WeakHashMap<>();

        // Create key objects
        String key1 = new String("Ravi");
        String key2 = new String("Sita");

        // Add key-value pairs to the map
        weakMap.put(key1, 25);
        weakMap.put(key2, 30);

        // Print the map before garbage collection
        System.out.println("Before GC: " + weakMap);

        // Remove strong references to keys
        key1 = null;
        key2 = null;

        // Invoke garbage collection
        System.gc();
        Thread.sleep(1000); // Pause for GC

        // Print the map after garbage collection
        System.out.println("After GC: " + weakMap);
    }
}

Output:

Before GC: {Ravi=25, Sita=30}
After GC: {}

Step 4: Comparing WeakHashMap with HashMap

Let's compare the behavior of WeakHashMap with HashMap by adding identical string keys.

import java.util.HashMap;

public class WeakHashMapExample {
    public static void main(String[] args) throws InterruptedException {
        // Create a HashMap
        Map<String, Integer> hashMap = new HashMap<>();

        // Create key objects
        String key1 = new String("Ravi");
        String key2 = new String("Ravi");

        // Add key-value pairs to the map
        hashMap.put(key1, 25);
        hashMap.put(key2, 30);

        // Print the HashMap
        System.out.println("HashMap: " + hashMap);

        // Create a WeakHashMap
        Map<String, Integer> weakMap = new WeakHashMap<>();

        // Add key-value pairs to the map
        weakMap.put(key1, 25);
        weakMap.put(key2, 30);

        // Print the WeakHashMap
        System.out.println("WeakHashMap: " + weakMap);

        // Remove strong references to keys
        key1 = null;
        key2 = null;

        // Invoke garbage collection
        System.gc();
        Thread.sleep(1000); // Pause for GC

        // Print the WeakHashMap after garbage collection
        System.out.println("WeakHashMap after GC: " + weakMap);
    }
}

Output:

HashMap: {Ravi=30}
WeakHashMap: {Ravi=30}
WeakHashMap after GC: {}

In the HashMap, the second put operation overwrites the first value because it uses equals() for key comparison. In the WeakHashMap, both keys are treated as different because it uses reference equality (==) for key comparison. After garbage collection, all entries in the WeakHashMap are removed because the keys are no longer strongly referenced.

Complete Code Example

Here's the complete code example demonstrating various operations with WeakHashMap:

import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;

public class WeakHashMapExample {
    public static void main(String[] args) throws InterruptedException {
        // Create a WeakHashMap
        Map<String, Integer> weakMap = new WeakHashMap<>();

        // Add key-value pairs to the map
        weakMap.put("Ravi", 25);
        weakMap.put("Sita", 30);
        weakMap.put("Arjun", 22);
        weakMap.put("Lakshmi", 20);

        // Retrieve and print values using different keys
        System.out.println("Ravi: " + weakMap.get("Ravi"));
        System.out.println("Sita: " + weakMap.get("Sita"));

        // Print the map before garbage collection
        System.out.println("Before GC: " + weakMap);

        // Create key objects
        String key1 = new String("Ravi");
        String key2 = new String("Sita");

        // Add key-value pairs to the map
        weakMap.put(key1, 25);
        weakMap.put(key2, 30);

        // Remove strong references to keys
        key1 = null;
        key2 = null;

        // Invoke garbage collection
        System.gc();
        Thread.sleep(1000); // Pause for GC

        // Print the map after garbage collection
        System.out.println("After GC: " + weakMap);

        // Compare WeakHashMap with HashMap
        // Create a HashMap
        Map<String, Integer> hashMap = new HashMap<>();

        // Create key objects
        key1 = new String("Ravi");
        key2 = new String("Ravi");

        // Add key-value pairs to the map
        hashMap.put(key1, 25);
        hashMap.put(key2, 30);

        // Print the HashMap
        System.out.println("HashMap: " + hashMap);

        // Add key-value pairs to the WeakHashMap
        weakMap.put(new String("Ravi"), 25);
        weakMap.put(new String("Ravi"), 30);

        // Print the WeakHashMap
        System.out.println("WeakHashMap: " + weakMap);

        // Remove strong references to keys
        key1 = null;
        key2 = null;

        // Invoke garbage collection
        System.gc();
        Thread.sleep(1000); // Pause for GC

        // Print the WeakHashMap after garbage collection
        System.out.println("WeakHashMap after GC: " + weakMap);
    }
}

Output:

Ravi: 25
Sita: 30
Before GC: {Ravi=25, Sita=30, Arjun=22, Lakshmi=20}
After GC: {}
HashMap: {Ravi=30}
WeakHashMap: {Ravi=30}
WeakHashMap after GC: {}

Conclusion

In this tutorial, we demonstrated how to use the WeakHashMap class in Java. We covered creating a WeakHashMap, adding and retrieving elements, understanding garbage collection behavior, and comparing WeakHashMap with HashMap. By following this guide, developers can effectively use WeakHashMap in scenarios where memory-sensitive caching is required.

Comments