Analysis of the difference between Weakhashmap and HashMap _java

Source: Internet
Author: User
Weakhashmap, the feature of this map is that when there are references to keys in addition to itself, there is no other reference to the key, and this map automatically discards this value.
See example: This example declares two map objects, one is HashMap, one is Weakhashmap, and puts a, b two objects into two maps, and when HashMap removes a and points A and B to null, A in the Weakhashmap is automatically recycled. The reason for this is that, for a object, when HashMap removes and points A to null, there is no pointer to a in addition to the Weakhashmap save a, so weakhashmap automatically discards a, For a B object, although it points to null, there is also a pointer to B in the HashMap, so
Weakhashmap will be retained
Copy Code code as follows:

Package test;

Import Java.util.HashMap;
Import Java.util.Iterator;
Import Java.util.Map;
Import Java.util.WeakHashMap;

public class Test {
public static void Main (string[] args) throws Exception {
String a = new string ("a");
String b = new String ("B");
Map Weakmap = new Weakhashmap ();
Map map = new HashMap ();
Map.put (A, "AAA");
Map.put (b, "BBB");


Weakmap.put (A, "AAA");
Weakmap.put (b, "BBB");

Map.Remove (a);

A=null;
B=null;

System.GC ();
Iterator i = Map.entryset (). iterator ();
while (I.hasnext ()) {
Map.entry en = (map.entry) i.next ();
SYSTEM.OUT.PRINTLN ("Map:" +en.getkey () + ":" +en.getvalue ());
}

Iterator J = Weakmap.entryset (). iterator ();
while (J.hasnext ()) {
Map.entry en = (map.entry) j.next ();
System.out.println ("Weakmap:" +en.getkey () + ":" +en.getvalue ());

}
}


}

First of all, let's make it clear:
Weakhashmap is mainly through the expungestaleentries of this function to achieve the purpose of removing the unused entries in order to achieve the automatic release of memory. Basically, you call this function when you access the content of the Weakhashmap, so that you can get rid of entries that are not internally referenced externally. 。 But if the weakhashmap is generated beforehand and the GC has not accessed the weakhashmap before, isn't it possible to free up memory?
Corresponding two test cases:
WeakHashMapTest1:
Copy Code code as follows:

public class WeakHashMapTest1 {
public static void Main (string[] args) throws Exception {
List<weakhashmap<byte[][], byte[][]>> maps = new arraylist<weakhashmap<byte[][], byte[][]>> ( );
for (int i = 0; i < 1000; i++) {
Weakhashmap<byte[][], byte[][]> d = new weakhashmap<byte[][], byte[][]> ();
D.put (New byte[1000][1000], new byte[1000][1000]);
Maps.add (d);
System.GC ();
System.err.println (i);}}}

Because the Java default memory is 64M, the test does not run in a few steps without changing the memory parameters, and the memory overflows. Sure enough, weakhashmap this time does not automatically help us release unused memory.
WeakHashMapTest2:
Copy Code code as follows:

public class WeakHashMapTest2 {
public static void Main (string[] args) throws Exception {
List<weakhashmap<byte[][], byte[][]>> maps = new arraylist<weakhashmap<byte[][], byte[][]>> ( );
for (int i = 0; i < 1000; i++) {
Weakhashmap<byte[][], byte[][]> d = new weakhashmap<byte[][], byte[][]> ();
D.put (New byte[1000][1000], new byte[1000][1000]);
Maps.add (d);
System.GC ();
System.err.println (i);
for (int j = 0; J < i; J + +) {
System.err.println (j + "size" + Maps.get (j). Size ());
}
}
}
}

This test output is normal and does not appear to be a memory overflow problem.
In summary: Weakhashmap is not what you do. He can automatically release objects that are not used internally, but release objects that are not in use when you access their content.
The question is clear, now let's comb it out. Understand the mysteries.
Weakhashmap implements a weak reference because its entry<k,v> is inherited from Weakreference<k>
This is written in the class definition and constructor of weakhashmap$entry<k,v>:
Copy Code code as follows:

private Static Class Entry<k,v>
Extends weakreference<k>
Implements Map.entry<k,v> Entry (K key, V value, referencequeue<k> queue,int hash, entry<k,v> next) {
Super (key, queue);
This.value = value;
This.hash = hash;
This.next = Next;
}

Note that it constructs the statement of the parent class: "Super (key, queue);", the key is passed in, so the key is weakly referenced, and value is a direct strong reference association in the This.value. at System.GC (), The byte array in the key is reclaimed, and value remains (value is strongly associated to entry, entry is associated with the map, and the map is associated with the ArrayList.).
How do I prove that the byte in key is recycled? You can analyze the memory image that is exported when memory overflows, or you can conclude by following a small test:
Replace the value above with a small object,
Copy Code code as follows:

for (int i = 0; i < 10000; i++) {
Weakhashmap<byte[][], object> d = new weakhashmap<byte[][], object> ();
D.put (New byte[1000][1000], new Object ());
Maps.add (d); System.GC ();
System.err.println (i);
}

The code above, even if executed 10,000 times, has no problem, and the byte array in the key is actually recycled.
In the For Loop, a new Weakhashmap is added each time, and after the put operation, although the GC reclaims the byte array in the WeakReference key and notifies the event to the Referencequeue, there is no corresponding action to trigger the Weakhashmap to deal with Referencequeue.
Therefore, the key of WeakReference packaging still exists in the Weakhashmap, and its corresponding value is of course there.
when was the value cleared?
Analysis of two examples shows that Maps.get (j) In example two. Size () triggers the recovery of value, and how it fires. View Weakhashmap source code It is known that the size method invokes the Expungestaleentries method. The method iterates through the entry (Quene) to be reclaimed by the VM, and the entry value is empty and the memory is reclaimed.
So the effect is that the key is cleared at the GC, and the value is cleared after the key clears the access Weakhashmap.
Question: Key Quene and map Quene is the same quene,poll operation will reduce a reference, the problem is the key if the first is cleared, Expungestaleentries Traverse Quene When the recovery of the key corresponding to the entry can also be taken out of it???
See WeakReference Referencequene about how the byte data in the key is recycled when executing SYSTEM.GC
Weakhashmap
public class Weakhashmap<k,v>
Extends abstractmap<k,v>
Implements Map<k,v>
A Map based on a hash table implemented with a weak key. In Weakhashmap, when a key is no longer in use, its entries are automatically removed.
More precisely, for a given key, the presence of the mapping does not prevent the garbage collector from discarding the key, which makes the key available to terminate and then be recycled.
When a key is discarded, its entries are effectively removed from the map, so the behavior of the class differs from other map implementations.
Both null values and NULL keys are supported. The class has performance characteristics similar to that of the HashMap class, and has the same initial capacity and load factor of the performance parameters.
Like most collection classes, this class is not synchronized. You can use the Collections.synchronizedmap method to construct synchronized Weakhashmap.
This class is used primarily with such key objects, whose equals method tests the identity of the object using the = = operator.
Once this key is discarded, it can never be created again, so it is not possible to find this key in Weakhashmap after a period of time, and you don't have to be surprised that its items have been removed.
This class is ideal for use with a key object that is not based on an object identifier, such as a String instance.
However, for this re-created key object, the Weakhashmap entry is automatically removed when the key is discarded, which is confusing.
The behavior of the Weakhashmap class depends partly on the actions of the garbage collector, so a few common (though not required) Map constants do not support this class.
Because the garbage collector can discard keys at any time, Weakhashmap is like an unknown thread that has been quietly removed from the entry.
In particular, the size method may return a smaller value after a period of time, even if the Weakhashmap instance is synchronized and no assignment method is invoked.
For the IsEmpty method, it is possible to return false and then return true, and for the given key, the ContainsKey method may return True and then return false, for the given key,
The Get method might return a value, but then return null, and the PUT method returns null for the key previously appearing in the map, and the Remove method returns False.
For a set of keys, a set of values, and an item set, the number of elements generated is getting smaller.
Each key object in the Weakhashmap is indirectly stored as an indication object for a weak reference. So, whether it's in the map or outside the map,
The key is automatically removed only after the garbage collector clears a weak reference to a key.
Implementation considerations: The Value object in Weakhashmap is persisted by a normal strong reference. Therefore, care should be taken to ensure that the value object does not strongly reference its own key directly or indirectly.
Because this prevents the key from being discarded. Note that a value object can indirectly refer to its corresponding key by Weakhashmap itself;
This means that a value object might strongly reference one of the other key objects, whereas the value object associated with that key object would instead strongly refer to the key of the first value object.
One way to handle this problem is to wrap the value itself in weakreferences before inserting it, such as: M.put (Key, new WeakReference (value)),
Then, the package is extracted separately using get.
All the iterators returned by the collection view method of the class are fast failures: After the iterator is created,
If the mapping is modified structurally, except through the Remove or add method of the iterator itself, any other time in any way,
Iterators will throw concurrentmodificationexception. Therefore, in the face of concurrent modifications, the iterator quickly fails completely,
Rather than risking any uncertain behavior at an uncertain time in the future.
Note that the rapid failure behavior of the iterator is not guaranteed, and in general, there is no firm guarantee when there are concurrent modifications to the different steps.
The fast fail iterator tries its best to throw concurrentmodificationexception. Therefore, it is wrong to write a method that relies on this exception program,
The correct approach is that the rapid failure behavior of the iterator should be used only to detect bugs.
Note that both the 1:null value and the null key are supported.
NOTE 2: Not thread-safe.
Note 3: The rapid failure behavior of iterators is not guaranteed.
Note that the 4:weakhashmap is disordered.
Note 5: Make sure that the value object does not strongly reference its own key directly or indirectly.
Because this prevents the key from being discarded. However, a value object can indirectly refer to its corresponding key by Weakhashmap itself;
This means that a value object might strongly reference a different key object, whereas a value object associated with that key object would instead strongly reference the key of the first value object, and then the loop would form.
One way to handle this problem is to wrap the value itself in weakreferences before inserting it, such as: M.put (Key, new WeakReference (value)),
Then, the package is extracted separately using get. As in instance 1.
Example 1:
Copy Code code as follows:

Import java.lang.ref.WeakReference;
Import Java.util.LinkedHashMap;
Import Java.util.Map;
Import Java.util.Random;
Import Java.util.WeakHashMap;
Import Java.util.concurrent.ConcurrentLinkedQueue;
public class Test {
/**
* @param args
*/
public static void Main (string[] args) {
Weakhashmap<integer,weakreference<people>> map=new Weakhashmap<integer,weakreference<people >> ();
People p1=new people ("Robin", 1,28);
People p2=new people ("Robin", 2,29);
People P3=new people ("Harry", 3,30);
Map.put (New Integer (m), new Weakreference<people> (p1));
Map.put (New Integer (), New weakreference<people> (p2));
Map.put (New Integer (1), New weakreference<people> (p3));

For (weakreference<people> rp:map.values ())
{
People p= Rp.get ();
System.out.println ("People:" +p);
}
}
}
Class people{
String name;
int id;
int age;
Public people (String name,int ID)
{
This (name,id,0);
}
Public people (String Name,int id,int age)
{
This.name=name;
This.id=id;
This.age=age;
}
Public String toString ()
{
return id+name+age;
}
public boolean equals (Object O)
{
if (o==null)
return false;
if (!) ( o instanceof people))
return false;
People p= (People) O;
Boolean res=name.equals (P.name);
if (res)
System.out.println ("name" +name+ "is Double");
Else
System.out.println (name+ "VS" +p.name);
return res;
}
public int hashcode ()
{
return Name.hashcode ();
}
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.