betacode

Руководство Java WeakHashMap

  1. WeakHashMap
  2. Primitive Keys
  3. Object Keys
  4. Зачем нам нужен WeakHashMap? 

1. WeakHashMap

WeakHashMap - это класс, аналогичный классу HashMap, все они используют метод хеширования (hashing technique) для хранения и извлечения данных. Разница в том, что если объект указан в качестве ключа of WeakHashMap, он может быть удален из памяти Garbage Collector (GC) (сборщиком мусора), если он больше не используется в другом месте, более сильном, чем GC. Как только ключ удаляется by GC, соответствующее отображение также удаляется из WeakHashMap.
В обычном смысле, если объект где-то используется, он полезен и не может быть удален из памяти. Однако WeakHashMap специально разработан и считается более слабым, чем GC, объектом, ключ которого все еще может быть удален из памяти.
public class WeakHashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>
Класс AnyObject будет участвовать в примерах, приведенных в этой статье:
AnyObject.java
package org.o7planning.beans;

public class AnyObject  {
    private String s;
    public AnyObject(String s)  {
        this.s = s;
    }
    public String getS() {
        return s;
    }
}
Сначала давайте рассмотрим пример ниже, а затем проанализируем, что произошло:
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) - Сначала, создается ссылка objK1 и указывается на объект AnyObject("S1"), который является ключом WeakHashMap.
(2) - ссылка objK1 указывает на нулевое значение null. В настоящее время больше нет никаких сильных ссылок, указывающих на объект AnyObject("S1"). Хотя он используется в качестве ключа of WeakHashMap, он по-прежнему считается подходящим для удаления сборщиком мусора (Garbage Collector). Поскольку GC считается более сильным, чем WeakHashMap.
Garbage Collector
Garbage Collector of Java работает автоматически для удаления неиспользуемых объектов из памяти. Вы можете активно вызывать его с помощью метода System.gc(), но нет никакой гарантии, что он вступит в силу немедленно.
  • Java Garbage Collector
В приведенном выше примере, если мы заменим WeakHashMap на HashMap, объект AnyObject("S1") не будет удален by Garbage Collector. Потому что HashMap считается более сильным, чем 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}
В этой статье мы обсудим различные ключевые типы of WeakHashMap и то, как GC обрабатывает их.
No
Key Type
Example
1
Primitive
Integer aKey = 3;
String aKey = "aString";
2
Object
newAnyObject();
newString("aString");
newInteger(3);

2. Primitive Keys

Объекты, созданные из примитивных значений, которые не используют оператор "new", не будут удалены by GC, если он используется в качестве ключа of WeakHashMap.
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

Объекты, созданные с помощью оператора "new", будут удалены из памяти by GC, если нет сильной ссылки, указывающей на него, даже если он используется в качестве ключа of WeakHashMap. Как уже упоминалось выше, GC считается более сильным, чем WeakHashMap.
Object Keys
AnyObject objK1 = new AnyObject("S1");
String objK2 = new String("S2");
Integer objK3 = new Integer(1000);
String objK4 = new String("S4");
Например:
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}
Объекты, созданные оператором "new", будут удалены из памяти by GC, если программе требуется больше памяти и если нет сильных ссылок, указывающих на нее. В этом случае вам не нужно активно вызывать метод System.gc().
В приведенном ниже примере мы пытаемся заполнить память, непрерывно создавая множество объектов.
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. Зачем нам нужен WeakHashMap? 

В принципе, WeakHashMap - это решение для экономии памяти, которое полезно, если вам нужен объект Map для хранения сопоставлений для ключей, которые вы знаете одновременно. Ключи, которые больше не нужны, автоматически удаляются by GC.
Помимо характеристик, упомянутых выше, WeakHashMap обладает всеми характеристиками обычной Map. Вы можете узнать больше о том, как использовать Map, в статье ниже:
Подробнее: