WeakHashMap是Map接口的一个实现,Grabage Collector可以回收值对象的内存 如果相应的密钥不再被任何程序部分引用。因此,如果密钥不再用于程序中。它的进入 对象将被垃圾收集,无论其使用情况如何。它清晰到这里
这与HashMap不同,即使不再引用key,值对象仍保留在HashMap中。我们需要明确地打电话 HashMap对象上的remove()方法删除值。调用remove将只删除map中的条目。它对GC的准备就绪了 取决于它是否仍然在程序中的某个地方使用。
Please find this coding example explaining above
根据我的理解,在HashMap上使用WeakHashMap
我的理解是,只有当我们想要确保Grabage Collector回收值对象时,才应该使用WeakHashMap 密钥不再由任何程序部分引用。这使程序内存有效我的理解是正确的吗?
根据JavaDocs使用WeakHashMap,我可以发现此声明
此类主要用于等于的关键对象 方法使用==运算符测试对象标识。
我没有得到上述声明的含义以及它与我对WeakHashMap用法的理解形成鲜明对比。实际上我没有得到这个陈述与WeakHashMap的使用有什么关系?
更新: - 进一步仔细阅读以下声明javadocs
WeakHashMap中的条目将在其键时自动删除 不再是一般用途。更准确地说,存在一个 给定密钥的映射不会阻止密钥被丢弃 由垃圾收集器,即,最终确定,最终确定,和 然后回收。当一个密钥被丢弃时,它的输入是有效的 从地图中删除,所以这个类的行为有点不同 其他Map实现。
我为了我和他人的利益而修改我的理解
根据我的修订理解,将WeakHashMap用于HashMap
我们应该只在我们想要确保在GC运行时从地图中删除键值对时才能使用WeakHashMap,而键不再是普通用途而不是地图本身。
例如: -
WeakHashMap<Integer, String> numbers = new WeakHashMap<Integer, String>();
numbers.put(new Integer(1), "one");// key only used within map not anywhere else
numbers.put(new Integer(2), "two");
System.out.println(numbers.get(new Integer(1))); // prints "one"
System.gc();
// let's say a garbage collection happens here
System.out.println(numbers.get(new Integer(1))); // prints "null"
System.out.println(numbers.get(new Integer(2))); // prints "null"
Object key = new Object();
m1.put(key, c1);
System.out.println(m1.size());
key = null or new Object() ; // privious key only used within map not anywhere else
System.gc();
Thread.sleep(100);
System.out.println(m1.size());
答案 0 :(得分:2)
这是因为当对象不再具有来自程序的任何其他部分的强引用时,对象将被垃圾收集(GCed)。
给定WeakHashMap<MyObject, String>
然后我们执行以下操作:
MyObject mo = new MyObject();
map.put(mo, "Test");
mo = null;
然后条目mo -> Test
将有资格获得GC。这意味着如果您有一个自定义.equals
实现使用MyObject
的某些属性来测试相等性,那么以后就不能这样做了:
MyObject mo2 = new MyObject();
map.get(mo2);
因为即使您重写的.equals
方法可能会说mo2.equals(mo) == true
,但mo2 == mo
并非如此,因此该条目可能已经过GC。
关键在于,如果您保留对mo
的引用并使用该引用从Map
检索值,那么该引用必须== mo
,因此有两件事情是的:
mo -> Test
无法加入==
的{{1}}方法从地图中检索条目基本上;由于GC将使用强引用来测试对象是否可以进行GC操作,因此最好确保您的.equals
方法执行相同操作以避免混淆。
答案 1 :(得分:1)
文档意味着此代码不是很有用:
WeakHashMap<Integer, String> numbers = new WeakHashMap<Integer, String>();
numbers.put(new Integer(1), "one");
numbers.put(new Integer(2), "two");
System.out.println(numbers.get(new Integer(1))); // prints "one"
// let's say a garbage collection happens here
System.out.println(numbers.get(new Integer(1))); // prints "null"
System.out.println(numbers.get(new Integer(2))); // prints "null"
对于任何不同实例可以相等的类,都会发生这种情况。 javadoc只是警告你,如果你没有注意到,这是没有用的。
答案 2 :(得分:1)
运行此测试
Object key = new Object();
WeakHashMap m = new WeakHashMap();
m.put(key, 1);
System.out.println(m.size());
key = null;
System.gc();
Thread.sleep(100);
System.out.println(m.size());
虽然System.gc不保证运行GC但是在我的Oracle JVM 7上它始终运行并打印此测试
1
0
这意味着GC从地图中删除了该条目,因为除了地图本身
之外,没有从任何地方引用该键答案 3 :(得分:0)
我认为这意味着相等的对象测试是在内存中使用对象位置,而不仅仅是因为两个不同的实例在其值中恰好相等。
如果不是这种情况,则很难判断该键是否被引用了更多且不同但是“相等”的值,实例可能会被引用并用于查找该值。
如果它说密钥必须具有引用相等性,那么你可能会更清楚,这样你就知道什么时候密钥不再被WeakHashMap实例的其他任何东西引用
答案 4 :(得分:0)
在Evgeniy Dorofeev回答的基础上,这是一个带有一些问题的例子:
import java.util.Map;
import java.util.WeakHashMap;
public class WeakHashMapTest {
public static void main(String[] args) throws InterruptedException {
String key = new String();
Map<String, String> m = new WeakHashMap();
m.put(key, "value");
System.out.println(m.size());
m.put("key", "value");
System.out.println(m.size());
m.put(new String(), "value");
System.out.println(m.size());
m.put(new String("k"), "value");
System.out.println(m.size());
key = null;
System.gc();
Thread.sleep(100);
System.out.println(m.size());
}
}
1
2
2
3
1