Руководство Java 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}
- HashMap
- LinkedHashMap
- TreeMap
- IdentityHashMap
- EnumMap
- ConcurrentSkipListMap
- ConcurrentHashMap
В этой статье мы обсудим различные ключевые типы 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, в статье ниже:
Подробнее:
Руководства Java Collections Framework
- Руководство Java PriorityBlockingQueue
- Руководство Java Collections Framework
- Руководство Java SortedSet
- Руководство Java List
- Руководство Java Iterator
- Руководство Java NavigableSet
- Руководство Java ListIterator
- Руководство Java ArrayList
- Руководство Java CopyOnWriteArrayList
- Руководство Java LinkedList
- Руководство Java Set
- Руководство Java TreeSet
- Руководство Java CopyOnWriteArraySet
- Руководство Java Queue
- Руководство Java Deque
- Руководство Java IdentityHashMap
- Руководство Java WeakHashMap
- Руководство Java Map
- Руководство Java SortedMap
- Руководство Java NavigableMap
- Руководство Java HashMap
- Руководство Java TreeMap
- Руководство Java PriorityQueue
- Руководство Java BlockingQueue
- Руководство Java ArrayBlockingQueue
- Руководство Java TransferQueue
Show More