容器类中有一种特殊的 Map:WeakHashMap,它被用来保存 WeakReference。它使得
“规范映射” (canonicalized mappings)更易于使用。在这种映射中,每个“值”只保
存一份实例以节省存储空间。当程序需要那个“值”的时候,便在映射中查询现有的对象,
然后使用它(而不是重新再创建)。可将“值”作为“规范映射”的一部分,一同初始化,
不过通常是在需要的时候才生成“值”。
这是一种节约存储空间的技术,因为 WeakHashMap 允许垃圾回收器自动清理“键”和
“值”,所以它显得十分便利。对于向 WeakHashMap 添加“键”和“值”的操作,则没
有什么特殊要求。WeakHashMap 会自动使用 WeakReference 包装它们。允许清理元素
的触发条件是,不再需要此“键”了,如下所示:
//: c11:CanonicalMapping.java
// Demonstrates WeakHashMap.
import java.util.*;
import java.lang.ref.*;
class Key {
private String ident;
public Key(String id) { ident = id; }
public String toString() { return ident; }
public int hashCode() { return ident.hashCode(); }
public boolean equals(Object r) {
return (r instanceof Key)
&& ident.equals(((Key)r).ident);
}
public void finalize() {
System.out.println("Finalizing Key "+ ident);
}
}
class Value {
private String ident;
public Value(String id) { ident = id; }
public String toString() { return ident; }
public void finalize() {
System.out.println("Finalizing Value " + ident);
}
}
public class CanonicalMapping {
public static void main(String[] args) {
int size = 1000;
// Or, choose size via the command line:
if(args.length > 0)
size = Integer.parseInt(args[0]);
Key[] keys = new Key[size];
WeakHashMap map = new WeakHashMap();
for(int i = 0; i < size; i++) {
Key k = new Key(Integer.toString(i));
Value v = new Value(Integer.toString(i));
if(i % 3 == 0)
keys[i] = k; // Save as "real" references
map.put(k, v);
}
System.gc();
}
} ///:~
如同本章前面所述,Key 类必须有 hashCode()和 equals(),因为在散列数据结构中,它
被用作“键”。
运行此程序,你会看到垃圾回收器会每隔三个“键”,就跳过一个,因为指向那个“键”
“规范映射” (canonicalized mappings)更易于使用。在这种映射中,每个“值”只保
存一份实例以节省存储空间。当程序需要那个“值”的时候,便在映射中查询现有的对象,
然后使用它(而不是重新再创建)。可将“值”作为“规范映射”的一部分,一同初始化,
不过通常是在需要的时候才生成“值”。
这是一种节约存储空间的技术,因为 WeakHashMap 允许垃圾回收器自动清理“键”和
“值”,所以它显得十分便利。对于向 WeakHashMap 添加“键”和“值”的操作,则没
有什么特殊要求。WeakHashMap 会自动使用 WeakReference 包装它们。允许清理元素
的触发条件是,不再需要此“键”了,如下所示:
//: c11:CanonicalMapping.java
// Demonstrates WeakHashMap.
import java.util.*;
import java.lang.ref.*;
class Key {
private String ident;
public Key(String id) { ident = id; }
public String toString() { return ident; }
public int hashCode() { return ident.hashCode(); }
public boolean equals(Object r) {
return (r instanceof Key)
&& ident.equals(((Key)r).ident);
}
public void finalize() {
System.out.println("Finalizing Key "+ ident);
}
}
class Value {
private String ident;
public Value(String id) { ident = id; }
public String toString() { return ident; }
public void finalize() {
System.out.println("Finalizing Value " + ident);
}
}
public class CanonicalMapping {
public static void main(String[] args) {
int size = 1000;
// Or, choose size via the command line:
if(args.length > 0)
size = Integer.parseInt(args[0]);
Key[] keys = new Key[size];
WeakHashMap map = new WeakHashMap();
for(int i = 0; i < size; i++) {
Key k = new Key(Integer.toString(i));
Value v = new Value(Integer.toString(i));
if(i % 3 == 0)
keys[i] = k; // Save as "real" references
map.put(k, v);
}
System.gc();
}
} ///:~
如同本章前面所述,Key 类必须有 hashCode()和 equals(),因为在散列数据结构中,它
被用作“键”。
运行此程序,你会看到垃圾回收器会每隔三个“键”,就跳过一个,因为指向那个“键”
的普通引用被存入了 keys 数组,所以那些对象不能被垃圾回收器回收。