Difference Between HashMap and WeakHashMap in Java
HashMap and WeakHashMap look the same from the outside: both implement Map, use hashing, and allow null keys and values. The crucial difference is how they hold their keys:
HashMapholds strong references. A key stays in memory as long as it is in the map, even if nothing else uses it.WeakHashMapholds keys through weak references. When no other strong reference to a key remains, the garbage collector may reclaim it, and its entry disappears from the map automatically.
1. Comparison Table
| Aspect | HashMap | WeakHashMap |
|---|---|---|
| Key references | Strong | Weak (WeakReference) |
| Entry lifetime | Until removed explicitly | Removed automatically after the key is garbage-collected |
| Size | Stable | Can shrink at any time, without your code removing anything |
| Values | Strong | Strong (a value referring back to its key prevents collection) |
| Nulls | One null key, null values | One null key, null values |
| Cloneable / Serializable | Yes | No |
| Typical use | General key–value storage | Metadata attached to objects, canonicalising caches |
| Thread-safe | No | No |
2. Garbage Collection in Action
import java.util.*;
public class WeakVsStrong {
static class Session {
final String user;
Session(String user) { this.user = user; }
public String toString() { return "Session(" + user + ")"; }
}
static void waitForGc(Map<?, ?> map, int expected) throws InterruptedException {
for (int i = 0; i < 50 && map.size() > expected; i++) { System.gc(); Thread.sleep(20); }
}
public static void main(String[] args) throws InterruptedException {
Map<Session, String> strong = new HashMap<>();
Map<Session, String> weak = new WeakHashMap<>();
Session s1 = new Session("asha"), s2 = new Session("ravi");
strong.put(s1, "cart-1"); strong.put(s2, "cart-2");
weak.put(new Session("asha"), "cart-1");
Session kept = new Session("ravi");
weak.put(kept, "cart-2");
s1 = null; s2 = null; // drop our references to the HashMap keys
waitForGc(weak, 1); // the weak key "asha" has no strong reference
System.out.println("HashMap size : " + strong.size() + " (keys kept alive by the map)");
System.out.println("WeakHashMap size : " + weak.size() + " (unreferenced key removed by GC)");
System.out.println("remaining weak : " + weak.keySet());
System.out.println("kept still used : " + kept.user);
}
}
HashMap size : 2 (keys kept alive by the map) WeakHashMap size : 1 (unreferenced key removed by GC) remaining weak : [Session(ravi)] kept still used : ravi
After the program drops its references, the HashMap still keeps both sessions alive, a classic source of memory leaks in caches. The WeakHashMap loses the entry whose key is no longer referenced elsewhere. Garbage collection timing is not guaranteed, so the example calls System.gc() repeatedly for the demonstration.
3. Use Case and Pitfalls
import java.util.*;
public class MetadataCache {
// Attach extra data to objects you don't own, without keeping them alive
static final Map<Object, String> labels = new WeakHashMap<>();
public static void main(String[] args) throws InterruptedException {
Object widget = new Object();
labels.put(widget, "primary button");
System.out.println("label: " + labels.get(widget));
widget = null; // widget no longer used anywhere
for (int i = 0; i < 50 && !labels.isEmpty(); i++) { System.gc(); Thread.sleep(20); }
System.out.println("entries after widget is gone: " + labels.size());
// Pitfall: String literals are interned and never collected, so they make poor weak keys
Map<String, Integer> literals = new WeakHashMap<>();
literals.put("constant", 1);
System.gc();
System.out.println("literal key still present: " + literals.containsKey("constant"));
}
}
label: primary button entries after widget is gone: 0 literal key still present: true
- Good use: associating extra data with objects whose lifetime you do not control (UI components, class loaders, request objects), so the data disappears with the object.
- String literals and boxed small integers are cached by the JVM and never collected, so they make useless weak keys.
- Values must not reference their keys, or the keys stay strongly reachable.
- Iteration results and
size()can change between calls; treat the map as a cache, not as reliable storage. - For real caches with size limits and expiry, prefer a library such as Caffeine; for value-based caches,
SoftReferenceis sometimes more appropriate.
4. Summary
HashMapkeeps keys alive;WeakHashMaplets the GC remove entries whose keys are no longer used.- Both allow nulls, use hashing and are not thread-safe.
- Use
WeakHashMapfor metadata tied to object lifetimes, not for normal data. - Avoid interned or cached objects as weak keys.
Related Tutorials
Frequently Asked Questions (FAQ)
Q1. What is the main difference between HashMap and WeakHashMap?
HashMap holds keys strongly; WeakHashMap holds them weakly, so entries are removed once their keys are garbage-collected.
Q2. When does WeakHashMap remove an entry?
After the garbage collector clears the weak reference to its key, the next map operation expunges the stale entry.
Q3. Are WeakHashMap values weak too?
No. Only keys are weakly referenced; values are strong.
Q4. Why are String literals bad keys for WeakHashMap?
Literals are interned and stay strongly reachable from the string pool, so their entries are never removed.
Q5. Can WeakHashMap help prevent memory leaks?
Yes, when metadata would otherwise keep objects alive after they are no longer used.
Q6. Does WeakHashMap allow null keys?
Yes, one null key, and null values.
Q7. Is WeakHashMap thread-safe?
No. Wrap it with Collections.synchronizedMap if it is shared.
Q8. Why might size() change unexpectedly?
The garbage collector can clear keys at any time, so stale entries are removed during later operations.
Q9. What is a weak reference?
A reference that does not prevent its object from being garbage-collected. java.lang.ref.WeakReference provides it.
Q10. Is WeakHashMap good for caching?
Only for caches keyed by objects whose lifetime should control the entry. For general caching with size limits or expiry, use a caching library.
Q11. What is the difference between weak and soft references?
Weakly reachable objects are collected at the next GC; softly reachable ones are kept until memory runs low.
Q12. Does WeakHashMap use equals and hashCode?
Yes, like HashMap. IdentityHashMap is the variant that compares by reference.
Q13. Can a value prevent its key from being collected?
Yes. If the value holds a strong reference to the key, the key stays reachable and the entry is never removed.
Q14. Is WeakHashMap serializable?
No, and it does not implement Cloneable either.
Q15. Which is faster?
HashMap; WeakHashMap has extra work managing references and expunging stale entries.
Q16. Can I force WeakHashMap entries to be removed?
Not reliably. System.gc() is only a request; remove entries explicitly if you need control.
Q17. What real-world code uses WeakHashMap?
Frameworks use it for per-object or per-class-loader metadata, listener registries and canonicalisation maps.
Q18. Do both have the same time complexity?
Yes, O(1) average for get and put.
Q19. Are boxed Integers good weak keys?
No. Values from −128 to 127 are cached by Integer.valueOf and never collected.
Q20. Is this asked in interviews?
Sometimes, in questions about memory leaks and references. Explain weak keys, GC behaviour and suitable use cases.