WeakHashMap vs HashMap
在下面的代码示例中,当键设置为null并且调用System.gc()
, WeakHashMap
丢失所有映射并清空。
class WeakHashMapExample { public static void main(String[] args) { Key k1 = new Key("Hello"); Key k2 = new Key("World"); Key k3 = new Key("Java"); Key k4 = new Key("Programming"); Map wm = new WeakHashMap(); wm.put(k1, "Hello"); wm.put(k2, "World"); wm.put(k3, "Java"); wm.put(k4, "Programming"); k1=null; k2=null; k3=null; k4=null; System.gc(); System.out.println("Weak Hash Map :"+wm.toString()); } } class Key{ private String key; public Key(String key) { this.key=key; } @Override public boolean equals(Object obj) { return this.key.equals((String)obj); } @Override public int hashCode() { return key.hashCode(); } @Override public String toString() { return key; } }
Output: Weak Hash Map :{}
当WeakHashMap
与HashMap
一起使用并且键设置为null时, WeakHashMap
不会丢失其键值映射。
class WeakHashMapExample { public static void main(String[] args) { Key k1 = new Key("Hello"); Key k2 = new Key("World"); Key k3 = new Key("Java"); Key k4 = new Key("Programming"); Map wm = new WeakHashMap(); Map hm=new HashMap(); wm.put(k1, "Hello"); wm.put(k2, "World"); wm.put(k3, "Java"); wm.put(k4, "Programming"); hm.put(k1, "Hello"); hm.put(k2, "World"); hm.put(k3, "Java"); hm.put(k4, "Programming"); k1=null; k2=null; k3=null; k4=null; System.gc(); System.out.println("Weak Hash Map :"+wm.toString()); System.out.println("Hash Map :"+hm.toString()); } } class Key{ private String key; public Key(String key) { this.key=key; } @Override public boolean equals(Object obj) { return this.key.equals((String)obj); } @Override public int hashCode() { return key.hashCode(); } @Override public String toString() { return key; } }
输出: Weak Hash Map :{Java=Java, Hello=Hello, World=World, Programming=Programming}
Hash Map :{Programming=Programming, World=World, Java=Java, Hello=Hello}
我的问题是为什么即使在丢弃密钥之后, WeakHashMap
也不会在第二个代码示例中丢失其条目?
当密钥不再可从实时代码中强烈访问时, WeakHashMap
会丢弃条目。 由于HashMap
维护对密钥的硬引用,因此密钥仍可访问,而WeakHashMap
不会丢弃条目。
关键是行为与对关键对象的引用有关,而不是与曾经可能具有对键的引用的任何变量的值有关。
您已在指针k1,k2,k3,k4
上设置null
k1,k2,k3,k4
但HashMap
和WeakHashMap
仍包含对这些Keys
引用。 因为HashMap
包含引用,GC的实际实例不会被GC删除。 WeakHashMap
仍然打印所有这些。
尝试仅使用HashMap
运行此示例 – >即使您已经清除了那些参考, HashMap
仍将保留它们。
必须在其他地方丢弃对象 ,然后WeakHashMap清除该对象。 像WeakReference一样,它的目的是记住一个对象,如果它仍在使用中。 不会造成内存泄漏永远持有一个对象。
在你的例子中设置hm = null;
看看WeakHashMap清理的神奇之处。
HashMap支配gc(垃圾收集器)。
gc支配WeakHashMap。
即使我们在k1,k2,k3,k4 gc上设置null也不会从HashMap中删除,因为gc将它们全部删除并为WeakHashMap提供空映射,因此名称为WeakHashMap