WeakHashMap and IdentityHashMap in Java
WeakHashMap and IdentityHashMap are two special-purpose Map implementations in java.util. WeakHashMap holds its keys weakly: when a key is no longer used anywhere else in the program, the garbage collector may remove it, and its entry disappears from the map. IdentityHashMap compares keys with == (the same object) instead of equals (equal content). They are rarely needed, but they solve a few problems no other map can. In this lesson, you will learn how each works and when to use it.
WeakHashMap
A normal HashMap keeps a strong reference to each key, so a key stays in memory as long as it is in the map, even if nothing else uses it. A WeakHashMap keeps a weak reference: if the only remaining reference to a key is the map's, the garbage collector is allowed to free the key, and the map then removes that entry automatically.
Features of WeakHashMap
- Entries vanish when their keys are garbage collected.
- Useful for caches and metadata attached to objects owned elsewhere.
- Allows
nullkeys and values. - Not synchronized.
- Its size can change between two calls without your code touching it.
Example: An Entry Disappears
Let's see an example where a key loses its last outside reference. Garbage collection can't be forced, only requested, so the output may differ between runs.
import java.util.Map;
import java.util.WeakHashMap;
public class WeakDemo {
public static void main(String[] args) throws InterruptedException {
Map<Object, String> cache = new WeakHashMap<>();
Object navikaKey = new Object();
Object srihithaKey = new Object();
cache.put(navikaKey, "Navika's thumbnail");
cache.put(srihithaKey, "Srihitha's thumbnail");
System.out.println("Before: " + cache.size() + " entries");
navikaKey = null;
System.gc();
Thread.sleep(100);
System.out.println("After: " + cache.size() + " entries");
System.out.println("Srihitha still cached? "
+ cache.containsKey(srihithaKey));
}
}Before: 2 entries
After: 1 entries
Srihitha still cached? trueExplanation: Setting navikaKey to null removed the last strong reference to that key object. After the garbage collector ran, the map dropped its entry. srihithaKey is still used by the program, so its entry stays.
Choosing Keys for a WeakHashMap
IdentityHashMap
IdentityHashMap breaks the normal Map rule on purpose: two keys are the same only if they are the same object (k1 == k2). It uses System.identityHashCode instead of the key's hashCode.
Features of IdentityHashMap
- Compares keys with
==, notequals. - Useful for tracking objects themselves: for example, "have I already visited this exact object?" when copying or serializing a graph of objects.
- Allows
nullkeys and values. - Not synchronized.
Example: Equal Strings, Different Objects
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;
public class IdentityDemo {
public static void main(String[] args) {
String a = new String("Navika");
String b = new String("Navika");
System.out.println("a.equals(b): " + a.equals(b)
+ ", a == b: " + (a == b));
Map<String, Integer> normal = new HashMap<>();
normal.put(a, 1);
normal.put(b, 2);
System.out.println("HashMap size: " + normal.size());
Map<String, Integer> identity = new IdentityHashMap<>();
identity.put(a, 1);
identity.put(b, 2);
System.out.println("IdentityHashMap size: " + identity.size());
}
}a.equals(b): true, a == b: false
HashMap size: 1
IdentityHashMap size: 2Explanation: a and b have the same characters but are two different objects. HashMap uses equals, so it treats them as one key and keeps size 1. IdentityHashMap uses ==, so it stores two entries.
Comparison
| HashMap | WeakHashMap | IdentityHashMap | |
|---|---|---|---|
| Key comparison | equals | equals | == |
| Hash used | hashCode() | hashCode() | System.identityHashCode() |
| Keeps keys alive | Yes | No | Yes |
| Typical use | General purpose | Caches tied to object lifetime | Tracking exact objects |
Common Mistakes
Using WeakHashMap as a general-purpose cache. Entries disappear only when keys are collected, not when memory is low by your rules; use a caching library for size or time limits.
Using IdentityHashMap with strings or numbers you look up by value. Equal values in different objects won't be found.
Practice
- Easy: Change
IdentityDemoto use the string literal"Navika"for bothaandb. What sizes are printed, and why? - Harder: Use an
IdentityHashMap<Object, Boolean>to count how many distinct objects are in a list that contains some objects more than once and some equal-but-separate objects.
Key Takeaways
Was this tutorial helpful?