WeakHashMap vs HashMap

China☆狼群 提交于 2019-12-03 05:13:32

问题


In the following code example when keys are set to null and System.gc() is called, the WeakHashMap loses all mappings and is emptied.

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<Key, String> wm = new WeakHashMap<Key, String>();


    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 :{}

When WeakHashMap is used along with HashMap and keys are set to null, the WeakHashMap doesn't lose its key-value mappings.

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<Key, String> wm = new WeakHashMap<Key, String>();
    Map<Key, String> hm=new HashMap<Key, String>();

    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;
}

}

Output: Weak Hash Map :{Java=Java, Hello=Hello, World=World, Programming=Programming} Hash Map :{Programming=Programming, World=World, Java=Java, Hello=Hello}

My question is why doesn't the WeakHashMap lose its entries in the second code example even after the keys are discarded?


回答1:


A WeakHashMap discards entries when the key is no longer strongly reachable from live code. Since the HashMap maintains a hard reference to the keys, the keys are still reachable and the WeakHashMap doesn't discard the entries.

The point is that the behavior has to do with references to the key objects, not to the value of any variable that might have at one time had a reference to the keys.




回答2:


An object must be discarded everywhere else, and then the WeakHashMap clears that object. Like a WeakReference its purpose is to remember an object if it is still in use. Without causing a memory leak forever holding an object.

In your example set hm = null; to see the magic of the WeakHashMap cleaning up.




回答3:


You have set null on pointers k1,k2,k3,k4 but HashMap and WeakHashMap still contains references to those Keys. And because HashMap is containing reference, actual instances of Keys are not deleted by GC. WeakHashMap still prints all of them.

Try run this example only with HashMap -> even that you've nulled out those references HashMap will still keep them.




回答4:


HashMap dominates gc(garbage collector).

gc dominates WeakHashMap.

Even though we set null on k1,k2,k3,k4 gc wont remove from HashMap where as gc removes them all and provides us empty map for WeakHashMap hence the name WeakHashMap




回答5:


Try this one -

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<Key, String> hm=new HashMap<Key, String>();   
    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("Hash Map :"+hm);

    System.out.println("Same thing with weakHash Map - "); 

    k1 = new Key("Hello");
    k2 = new Key("World");
    k3 = new Key("Java");
    k4 = new Key("Programming");

    Map<Key, String> wm = new WeakHashMap<Key, String>();

    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);
}

}

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;
}

public void finalize() 
{ 
   System.out.println("Finalize method is called"); 
} 

}


来源:https://stackoverflow.com/questions/18965094/weakhashmap-vs-hashmap

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!