codestory

Die Anleitung zu Java WeakHashMap

  1. WeakHashMap
  2. Primitive Keys
  3. Object Keys
  4. Warum brauchen wir WeakHashMap? 

1. WeakHashMap

WeakHashMap ist eine Klasse ähnlich der Klasse HashMap, die alle hashing technique verwenden, um Daten zu speichern und abzurufen. Der Unterschied besteht darin, dass ein Objekt, das als Schlüssel von WeakHashMap angegeben ist, vom Garbage Collector (GC) aus dem Speicher entfernt werden kann, wenn es nicht mehr an einer anderen Stelle als GC verwendet wird. Sobald der Schlüssel von GC entfernt wurde, wird auch das entsprechende Mapping aus WeakHashMap entfernt.
Im normalen Gedanken ist ein Objekt, das irgendwo verwendet wird, nützlich und kann nicht aus dem Speicher entfernt werden. WeakHashMap ist jedoch speziell entwickelt und gilt als schwächer als GC, ein Objekt, dessen Schlüssel noch aus dem Speicher entfernt werden kann.
public class WeakHashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>
Die Klasse AnyObject wird an den Beispielen in diesem Artikel teilnehmen:
AnyObject.java
package org.o7planning.beans;

public class AnyObject  {
    private String s;
    public AnyObject(String s)  {
        this.s = s;
    }
    public String getS() {
        return s;
    }
}
Sehen wir uns zuerst das folgende Beispiel an, dann analysieren wir, was passiert ist:
WeakHashMap_objectKey_ex1.java
package org.o7planning.weakhashmap.ex;

import java.util.WeakHashMap;

import org.o7planning.beans.AnyObject;

public class WeakHashMap_objectKey_ex1 {

    public static void main(String[] args) throws InterruptedException {
        // (1) Create a reference objK1 points to AnyObject("S1") object.
        AnyObject objK1 = new AnyObject("S1");
        AnyObject objK2 = new AnyObject("S2");

        // Create WeakHashMap object:
        WeakHashMap<AnyObject,Integer> map = new  WeakHashMap<AnyObject,Integer>();
        
        map.put(objK1, 1000);
        map.put(objK2, 2000);
        
        System.out.println(map);
        
        // (2) Set reference objK1 to null.
        objK1 = null;
        
        // Garbage Collector is called
        System.gc();
        System.out.println("\n --- After Garbage Collector is called: --- \n");
        
        Thread.sleep(3000);
        System.out.println(map);
    }
}
Output:
{org.o7planning.beans.AnyObject@1c4af82c=2000, org.o7planning.beans.AnyObject@5e91993f=1000}

 --- After Garbage Collector is called: ---

{org.o7planning.beans.AnyObject@1c4af82c=2000}
(1) - Zuerst wird die Referenz objK1 erstellt und auf das Objekt AnyObject("S1") gezeigt, das ein Schlüssel von WeakHashMap ist.
(2) - Die Referenz objK1 zeigt auf einen Wert null. Zu diesem Zeitpunkt gibt es keine starken Verweise mehr, die auf das Objekt AnyObject("S1") verweisen. Obwohl es als Schlüssel von WeakHashMap verwendet wird, kann es dennoch von Garbage Collector entfernt werden. Da GC gilt stärker WeakHashMap.
Garbage Collector
Der Garbage Collector von Java arbeitet automatisch, um nicht verwendete Objekte aus dem Speicher zu entfernen. Sie können es mit der Methode System.gc() aktiv aufrufen, es gibt jedoch keine Garantie dafür, dass es sofort wirksam wird.
  • Java Garbage Collector
Wenn wir bei der Änderung des obigen Beispiel wird WeakHashMap durch HashMap ersetzen, wird das Objekt AnyObject("S1") nicht von Garbage Collector entfernt. Denn HashMap gilt als stärker als Garbage Collector.
HashMap_objectKey_ex1.java
package org.o7planning.weakhashmap.ex;

import java.util.HashMap;

import org.o7planning.beans.AnyObject;

public class HashMap_objectKey_ex1 {

    public static void main(String[] args) throws InterruptedException {
        // (1) Create a reference objK1 points to AnyObject("S1") object.
        AnyObject objK1 = new AnyObject("S1");
        AnyObject objK2 = new AnyObject("S2");

        // Create HashMap object:
        HashMap<AnyObject,Integer> map = new  HashMap<AnyObject,Integer>();
        
        map.put(objK1, 1000);
        map.put(objK2, 2000);
        
        System.out.println(map);
        
        // (2) Set reference objK1 to null.
        objK1 = null;
        
        // Garbage Collector is called
        System.gc();
        System.out.println("\n --- After Garbage Collector is called: --- \n");
        
        Thread.sleep(3000);
        System.out.println(map);
    }
}
Output:
{org.o7planning.beans.AnyObject@1c4af82c=2000, org.o7planning.beans.AnyObject@5e91993f=1000}

 --- After Garbage Collector is called: ---

{org.o7planning.beans.AnyObject@1c4af82c=2000, org.o7planning.beans.AnyObject@5e91993f=1000}
In diesem Artikel besprechen wir die verschiedenen Schlüsseltypen von WeakHashMap und wie GC sie behandelt.
No
Key Type
Example
1
Primitive
Integer aKey = 3;
String aKey = "aString";
2
Object
newAnyObject();
newString("aString");
newInteger(3);

2. Primitive Keys

Objekte, die aus primitiven Werten erstellt wurden, die keinen Operator "new" verwenden, werden von GC nicht entfernt, wenn sie als Schlüssel einer WeakHashMap verwendet werden
Primitive Keys
Integer key1 = 1000;
Double key2 = 2000.2;
String key3 = "SomeKey";
WeakHashMap_primitiveKey_ex1.java
package org.o7planning.weakhashmap.ex;

import java.util.WeakHashMap;

public class WeakHashMap_primitiveKey_ex1 {

    public static void main(String[] args) throws InterruptedException {
        // (1) Create a reference objK1 points to a primitive value.
        Integer objK1 = 100;
        Integer objK2 = 200;

        // Create WeakHashMap object:
        WeakHashMap<Integer, String> map = new WeakHashMap<Integer, String>();

        map.put(objK1, "One Hundred");
        map.put(objK2, "Two Hundred");

        System.out.println(map);

        // (2) Set reference objK1 to null.
        objK1 = null;

        // Garbage Collector is called
        System.gc();
        System.out.println("\n --- After Garbage Collector is called: --- \n");

        Thread.sleep(5000);
        System.out.println(map);
    }
}
Output:
{200=Two Hundred, 100=One Hundred}

 --- After Garbage Collector is called: ---

{200=Two Hundred, 100=One Hundred}

3. Object Keys

Objekte, die mit dem Operator "new" erstellt wurden, werden von GC aus dem Speicher entfernt, wenn kein starker Verweis darauf besteht, selbst wenn er als Schlüssel der WeakHashMap verwendet wird. Wie oben erwähnt, gilt GC als stärker als WeakHashMap.
Object Keys
AnyObject objK1 = new AnyObject("S1");
String objK2 = new String("S2");
Integer objK3 = new Integer(1000);
String objK4 = new String("S4");
Zum Beispiel:
WeakHashMap_objectKey_ex2.java
package org.o7planning.weakhashmap.ex;

import java.util.WeakHashMap;

import org.o7planning.beans.AnyObject;

public class WeakHashMap_objectKey_ex2 {

    public static void main(String[] args) throws InterruptedException {
        // (1) Create a reference objK1 points to String object.
        AnyObject objK1 = new AnyObject("S1");
        String objK2 = new String("S2");
        Integer objK3 = new Integer(1000);
        String objK4 = new String("S4");

        // Create WeakHashMap object:
        WeakHashMap<Object,Integer> map = new  WeakHashMap<Object,Integer>();
        
        map.put(objK1, 1000);
        map.put(objK2, 2000);
        map.put(objK3, 3000);
        map.put(objK4, 4000);
        
        System.out.println(map);
        
        // (2) Set references objK1, objK2, objK3 to null.
        objK1 = null;
        objK2 = null;
        objK3 = null;
        
        // Garbage Collector is called
        System.gc();
        System.out.println("\n --- After Garbage Collector is called: --- \n");
        
        Thread.sleep(3000);
        System.out.println(map);
    }
}
Output:
{S2=2000, org.o7planning.beans.AnyObject@5e91993f=1000, S4=4000, 1000=3000}

 --- After Garbage Collector is called: ---

{S4=4000}
Objekte, die mit dem Operator "new" erstellt wurden, werden von GC aus dem Speicher entfernt, wenn das Programm mehr Speicher benötigt und keine starken Referenzen darauf verweisen. In diesem Fall müssen Sie die Methode System.gc() nicht aktiv aufrufen.
Im folgenden Beispiel versuchen wir, den Speicher zu füllen, indem wir kontinuierlich viele Objekte erstellen.
WeakHashMap_objectKey_ex3.java
package org.o7planning.weakhashmap.ex;

import java.util.WeakHashMap;

import org.o7planning.beans.AnyObject;

public class WeakHashMap_objectKey_ex3 {

    public static void main(String[] args) throws InterruptedException {
        // (1) Create a reference objK1 points to String object.
        AnyObject objK1 = new AnyObject("S1");
        String objK2 = new String("S2");
        Integer objK3 = new Integer(1000);
        String objK4 = new String("S4");
        String objK5 = "S5"; // Primitive Key

        // Create WeakHashMap object:
        WeakHashMap<Object,Integer> map = new  WeakHashMap<Object,Integer>();
        
        map.put(objK1, 1000);
        map.put(objK2, 2000);
        map.put(objK3, 3000);
        map.put(objK4, 4000);
        map.put(objK5, 5000);
        
        int ORIGIN_MAP_SIZE = map.size();
        
        System.out.println(map);  
        
        int i = 0;
        while(true)  {
            if(map.size() < ORIGIN_MAP_SIZE) {
                System.out.println("WeakHashMap Size: " + map.size());
                System.out.println(map);
                break;
            }
            i++;
            // (2) Make the memory full by creating lots of Strings
            String s = new String("String" + i);
            System.out.println("Create new String: " + s);
            System.out.println("   >>> Now WeakHashMap size is: " + map.size());
        }
    }
}
Output:
{S2=2000, org.o7planning.beans.AnyObject@5e91993f=1000, S5=5000, S4=4000, 1000=3000}
Create new String: String1

....

Create new String: String347615
   >>> Now WeakHashMap size is: 5
Create new String: String347616
   >>> Now WeakHashMap size is: 5
Create new String: String347617
   >>> Now WeakHashMap size is: 5
WeakHashMap Size: 1
{S5=5000}

4. Warum brauchen wir WeakHashMap? 

Grundsätzlich ist WeakHashMap eine Lösung, um Speicher zu sparen, was nützlich ist, wenn Sie ein Objekt Map zum Speichern von Mapping für die Ihnen bekannten Schlüssel benötigen. Nicht mehr benötigte Schlüssel werden von GC automatisch entfernt.
Neben den oben genannten Eigenschaften hat WeakHashMap alle Eigenschaften einer regulären Map. Weitere Informationen zur Verwendung von Map finden Sie im folgenden Artikel
Mehr sehen: