问题
WeakHashMap is an implementation of Map interface where the memory of the value object can be reclaimed by Grabage Collector if the corresponding key is no longer referred by any section of program. So if key is no longer used in program. its Entry object will be garbage collected irrespective of its usage. Its clear till here
This is different from HashMap where the value object remain in HashMap even if key is no longer referred. We need to explicitly call remove() method on HashMap object to remove the value. calling remove will just remove the entry from map. Its readyness for GC will depend whether it is still used somewhere in program or not.
Please find this coding example explaining above
Usage of WeakHashMap over HashMap as per mine understanding
My understanding is we should go for WeakHashMap only when we want to ensure that value object is reclaimed by Grabage Collector when key is no longer referred by any section of program. This makes program memory efficient Is my understanding correct here?
Usage of WeakHashMap as per JavaDocs , i could spot this statement
This class is intended primarily for use with key objects whose equals methods test for object identity using the == operator.
I did not get what above statement meant and how it contrast with mine understanding of WeakHashMap usage. Actually i did not get how this statement is related to usage of WeakHashMap?
UPDATE:- on further carefully reading below statement the javadocs
An entry in a WeakHashMap will automatically be removed when its key is no longer in ordinary use. More precisely, the presence of a mapping for a given key will not prevent the key from being discarded by the garbage collector, that is, made finalizable, finalized, and then reclaimed. When a key has been discarded its entry is effectively removed from the map, so this class behaves somewhat differently from other Map implementations.
i am revising my understanding for the benefit of me and others
Usage of WeakHashMap over HashMap as per mine revised understanding
We should go for WeakHashMap only when we want to ensure that key-value pair is removed from map on GC run when key is no longer in ordinary use other than map itself.
Examples are :-
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());
回答1:
This is due to the fact that objects will be garbage collected (GCed) when they are no longer have a strong reference from any other part of the program.
Given a WeakHashMap<MyObject, String>
then if we do the following:
MyObject mo = new MyObject();
map.put(mo, "Test");
mo = null;
Then the entry mo -> Test
will be eligible for GC. This means that if you have a custom .equals
implementation that uses some property of MyObject
to test for equality then you cannot later do this:
MyObject mo2 = new MyObject();
map.get(mo2);
Because even though your overridden .equals
method may say that mo2.equals(mo) == true
it is not the case that mo2 == mo
and therefore the entry may have already been GCed.
The point is that if you keep a reference to mo
and use that to retrieve the value from the Map
then it is the case that that reference must == mo
and therefore two things are true:
- the entry
mo -> Test
cannot be gced - you can use an
==
based.equals
method to retrieve the entry from the map
Basically; as the GC will use strong references to test whether an object can be GCed it is best to ensure that your .equals
method does the same to avoid confusion.
回答2:
The documentation means that this code is not very useful:
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"
This would happen for any class where different instances can be equal. The javadoc is just warning you, in case you hadn't noticed already, that this is not helpful.
回答3:
Run this test
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());
though System.gc does not guarantee running GC but on my Oracle's JVM 7 it always runs and this test prints
1
0
which means that GC removed the entry from map because the key is not referenced from anywhere but map itself
回答4:
I think that this means that the object test for equality be using the objects location in memory and not just because two different instances happen to 'equal' in their values.
If this is not the case the it is difficult to tell if the key is referenced any more and a different, but 'equal'in values, instance might be referenced and used to look up the value.
It might be clearer if it said that the keys have to have reference equality so that you know when the keys are no longer referenced by anything other that the WeakHashMap instance
回答5:
Building on Evgeniy Dorofeev answer, here is an example with a few gotchas:
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());
}
}
Output
1
2
2
3
1
来源:https://stackoverflow.com/questions/20742956/usage-of-weakhashmap