Using WeakHashMap?

WeakHashMap is an implementation of the Map interface, where the memory of a value object can be restored by the Grabage Collector if the corresponding key is no longer transferred by any part of the program. Therefore, if the key is no longer used in the program. Upon its entry, the facility will collect garbage regardless of its use. It's clear so far

This is different from HashMap, where the value object remains in the HashMap, even if the key is no longer being passed. We need to explicitly call remove () on the HashMap object to remove the value. calling remove will simply remove the entry from the card. His readiness for GC will depend on whether he is used somewhere in the program or not.

This code example is explained above.

Using WeakHashMap on top of HashMap as I understand it

My understanding is that we should go for WeakHashMap only when we want the value object to be fixed by the Grabage Collector, when the key no longer refers to any section of the program. This makes program memory efficient. Is my understanding right here?

Using WeakHashMap on JavaDocs , I might notice this statement

This class is primarily intended for use with key objects whose equal methods verify the identity of the object using the == operator.

I did not understand what was meant above, and how this contrasts with my understanding of using WeakHashMap. In fact, I did not understand how this statement is related to the use of WeakHashMap?

UPDATE: - with further careful reading below the javadocs instructions

The entry in the WeakHashMap file is automatically deleted when its key is no longer used in normal mode. 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, completed, completed and then reclaimed. When a key has been discarded, its input is effectively removed from the card, therefore this class behaves somewhat differently than other card implementations.

I am redefining my understanding for the benefit of me and others.

Using WeakHashMap over HashMap as Per My Revised Understanding

We should go for WeakHashMap only when we want to make sure that the key-value pair is removed from the card when the GC starts, when the key is no longer used in the usual way, except for the card itself.

Examples: -

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 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()); 
+6
source share
5 answers

This is because objects will collect garbage (GCed) when they no longer have a strong link from any other part of the program.

Given 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 MyObject property to check for equality, you cannot do this later:

 MyObject mo2 = new MyObject(); map.get(mo2); 

Because, although your overridden .equals method may say that mo2.equals(mo) == true , this is not the case mo2 == mo , and therefore the entry may already be GCed.

The fact is that if you save a link to mo and use this to extract the value from Map , then in this case this link should == mo , and therefore two things are true:

  • record mo -> Test cannot be encoded
  • you can use the .equals based .equals method to retrieve the record from the map

Basically; since the GC will use strong links to check if the object can be GCed, it is best to ensure that your .equals method does the same to avoid confusion.

+2
source

Documentation means 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 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 will happen for any class where different instances can be equal. Javadoc just warns you if you have not noticed that this does not help.

+1
source

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

although System.gc does not guarantee that GC will start, but on my JVM server, Oracle 7 always runs, and this test prints

 1 0 

which means that GC deleted the record from the card because the key is not referenced anywhere except the card itself

+1
source

I think this means that the object equality test uses the location of objects in memory, and not just because two different instances have an equal value in their values.

If this is not the case, it is difficult to say whether the key refers to another, and to other values โ€‹โ€‹equal to "equal", the instance can be referenced and used to search for the value.

Perhaps it would be clearer if he said that the keys must have referential equality, so that you know when the keys no longer refer to anything else, that instance of WeakHashMap

0
source

Based on the answer of Evgeny Dorofeev, here is an example with several errors:

 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 
0
source

All Articles