存储Map的Entry是否安全?是否会引发内存泄漏?
The Problem Code
public Map<String, Integer> queryDatabase() { final Map<String, Integer> map = new TreeMap<>(); map.put("one", 1); map.put("two", 2); // ... return map; } public Map.Entry<String, Integer> getEntry(int n) { final Map<String, Integer> map = queryDatabase(); for (final Map.Entry<String, Integer> entry : map.entrySet()) { if (entry.getValue().equals(n)) return entry; // 模拟校验 } return null; }
My Question
Is it safe to store the Map.Entry obtained from the getEntry method? Could this lead to memory leaks?
Answer
Short answer: No, storing this Map.Entry is not safe—it absolutely can cause memory leaks.
Here's a breakdown of why:
- Every call to
getEntrycreates a brand-newTreeMapinstance viaqueryDatabase(). Normally, this map is a local variable, so once the method finishes running, the garbage collector (GC) should clean it up entirely. - But
TreeMapuses a red-black tree under the hood, and its entry objects (TreeNodeinstances) hold references to their parent, left, and right child nodes. When you hang onto one of these entries, you create a reference chain that keeps the entire tree (and thus the fullTreeMapinstance) in memory. The GC can't collect any of it because your stored entry links to the rest of the tree structure. - If you repeatedly call
getEntryand store the returned entries, you'll leave a fullTreeMapstranded in memory each time. Over time, this will build up into a noticeable memory leak.
Beyond memory issues, Map.Entry is meant as a view into the parent map, not a standalone data container. Even if the map wasn't stuck in memory, relying on an entry long-term is risky—if the map were ever modified (it's not exposed here, but still a good practice note), the entry's values could change unexpectedly.
Fix: Store the Data, Not the Entry
Instead of holding onto the Map.Entry, extract the key and value and save them in a simple, standalone object. For example:
// A basic POJO to hold your key-value pair public class KeyValuePair { private final String key; private final int value; public KeyValuePair(String key, int value) { this.key = key; this.value = value; } // Getters for access public String getKey() { return key; } public int getValue() { return value; } } // Modify your method to return this pair instead of the entry public KeyValuePair getKeyValue(int n) { final Map<String, Integer> map = queryDatabase(); for (final Map.Entry<String, Integer> entry : map.entrySet()) { if (entry.getValue().equals(n)) { return new KeyValuePair(entry.getKey(), entry.getValue()); } } return null; }
This way, you only keep the actual data you need, and the TreeMap can be properly garbage collected once the method finishes executing.
内容的提问来源于stack exchange,提问作者payloc91

