Java WeakHashMap 详解:原理、用法与与 HashMap 的关键差异
Java WeakHashMap
全面指南 Java WeakHashMap,涵盖创建、与 HashMap 核心差异、实战示例及关键方法。
WeakHashMap 类属于 Java 集合框架,实现 Map 接口。它表现如普通哈希表,但键以 弱引用 存储,当键不再被强引用时,垃圾回收器可回收其内存。
注意:WeakHashMap 的键包裹在 WeakReference 对象中。
若程序不再持有键对象的强引用,弱引用可被垃圾回收。
创建 WeakHashMap
先导入 java.util.WeakHashMap:
import java.util.WeakHashMap;
再实例化,可选指定初始容量和负载因子:
// 容量 8、负载因子 0.6 的 WeakHashMap
WeakHashMap<Key, Value> numbers = new WeakHashMap<>(8, 0.6);
参数:
- capacity — 扩容前可容纳的条目数。默认 16。
- loadFactor — 扩容阈值。默认 0.75。
无参数时使用默认值:
WeakHashMap<Key, Value> numbers = new WeakHashMap<>();
HashMap 与 WeakHashMap 的差异
两者均实现 Map,核心区别在于引用强度:
- HashMap — 键为强引用;条目持久存在直到显式移除。
- WeakHashMap — 键为弱引用;键不可达时条目自动消失。
演示行为差异的示例:
import java.util.WeakHashMap;
class Main {
public static void main(String[] args) {
WeakHashMap<String, Integer> numbers = new WeakHashMap<>();
String two = new String("Two");
Integer twoValue = 2;
String four = new String("Four");
Integer fourValue = 4;
numbers.put(two, twoValue);
numbers.put(four, fourValue);
System.out.println("WeakHashMap: " + numbers);
// 置空键引用
two = null;
System.gc();
System.out.println("GC 后的 WeakHashMap: " + numbers);
}
}
输出:
WeakHashMap: {Four=4, Two=2}
GC 后的 WeakHashMap: {Four=4}
"Two" 条目消失,因其键不再强可达。对比 HashMap 会保留条目:
import java.util.HashMap;
class Main {
public static void main(String[] args) {
HashMap<String, Integer> numbers = new HashMap<>();
String two = new String("Two");
Integer twoValue = 2;
String four = new String("Four");
Integer fourValue = 4;
numbers.put(two, twoValue);
numbers.put(four, fourValue);
System.out.println("HashMap: " + numbers);
two = null;
System.gc();
System.out.println("GC 后的 HashMap: " + numbers);
}
}
输出:
HashMap: {Four=4, Two=2}
GC 后的 HashMap: {Four=4, Two=2}
因此,当你希望 Map 自动释放未使用键占用的内存时,WeakHashMap 是理想选择。
从其他 Map 转换
用现有 Map 实例化 WeakHashMap 以复制条目:
import java.util.HashMap;
import java.util.WeakHashMap;
class Main {
public static void main(String[] args) {
HashMap<String, Integer> evenNumbers = new HashMap<>();
String two = new String("Two");
evenNumbers.put(two, 2);
System.out.println("HashMap: " + evenNumbers);
WeakHashMap<String, Integer> numbers = new WeakHashMap<>(evenNumbers);
System.out.println("WeakHashMap: " + numbers);
}
}
输出:
HashMap: {Two=2}
WeakHashMap: {Two=2}
WeakHashMap 的关键方法
以下为最常用操作精选。
插入条目
put(key, value)— 添加映射。putAll(map)— 合并另一个 Map。putIfAbsent(key, value)— 键缺失时才插入。
示例:
import java.util.WeakHashMap;
class Main {
public static void main(String[] args) {
WeakHashMap<String, Integer> evenNumbers = new WeakHashMap<>();
evenNumbers.put(new String("Two"), 2);
evenNumbers.putIfAbsent(new String("Four"), 4);
System.out.println("Even numbers: " + evenNumbers);
WeakHashMap<String, Integer> numbers = new WeakHashMap<>();
numbers.put(new String("One"), 1);
numbers.putAll(evenNumbers);
System.out.println("All numbers: " + numbers);
}
}
输出:
Even numbers: {Four=4, Two=2}
All numbers: {Two=2, Four=4, One=1}
访问条目
通过以下方式获取数据:
get(key)— 返回值或null(缺失时)。getOrDefault(key, default)— 键缺失时返回默认值。entrySet()、keySet()、values()— 遍历条目、键或值。
示例:
import java.util.WeakHashMap;
class Main {
public static void main(String[] args) {
WeakHashMap<String, Integer> numbers = new WeakHashMap<>();
numbers.put(new String("One"), 1);
numbers.put(new String("Two"), 2);
System.out.println("Map: " + numbers);
System.out.println("Entry set: " + numbers.entrySet());
System.out.println("Keys: " + numbers.keySet());
System.out.println("Values: " + numbers.values());
System.out.println("Get Two: " + numbers.get("Two"));
System.out.println("GetOrDefault Four: " + numbers.getOrDefault("Four", 4));
}
}
输出:
Map: {Two=2, One=1}
Entry set: [Two=2, One=1]
Keys: [Two, One]
Values: [1, 2]
Get Two: 2
GetOrDefault Four: 4
移除条目
remove(key)— 移除并返回值。remove(key, value)— 仅当当前映射匹配提供的值时移除。clear()— 清空 Map。containsKey(key)、containsValue(value)、size()、isEmpty()
示例:
import java.util.WeakHashMap;
class Main {
public static void main(String[] args) {
WeakHashMap<String, Integer> numbers = new WeakHashMap<>();
numbers.put(new String("One"), 1);
numbers.put(new String("Two"), 2);
System.out.println("Map: " + numbers);
int removed = numbers.remove("Two");
System.out.println("移除的值: " + removed);
boolean removedIf = numbers.remove("One", 3);
System.out.println("是否移除 {One=3}? " + removedIf);
System.out.println("移除后: " + numbers);
}
}
输出:
Map: {Two=2, One=1}
移除的值: 2
是否移除 {One=3}? false
移除后: {One=1}
其他工具方法
| 方法 | 说明 |
|---|---|
clear() | 删除所有条目 |
containsKey(key) | 检查键是否存在 |
containsValue(value) | 检查值是否存在 |
size() | 返回条目数量 |
isEmpty() | Map 为空返回 true |
深入了解请参阅官方 Java WeakHashMap 文档。
java
- 精通 Java 运算符:类型、语法与实战示例
- Java 注释:类型、用法与最佳实践
- 精通 Java if…else:控制流全解析
- 精通 Java 增强 for 循环:语法、示例与最佳实践
- Java break 语句:用法、时机与标签 break 详解
- 精通 Java 字符串:创建、方法与最佳实践
- 精通 Java 接口:概念、实现与最佳实践
- 精通 Java 匿名内部类:定义、语法与实战示例
- 精通 Java Try-With-Resources:自动资源管理详解
- Java 注解详解:类型、放置位置与实战示例
- Java 断言实战指南:尽早发现 Bug 与保障代码可靠性
- 深入理解 Java Vector:用法、特性及与 ArrayList 的对比