1. HashMultimap 概述
介绍:
HashMultimap 是一种允许一个键(key)映射到多个值(value)的集合类型,它属于"Multimap"家族。与传统的 Map<K, V> 不同,HashMultimap 更像是 Map<K, Collection<V>> 的增强封装。
主要特性:
- 一键多值:单个键可以关联多个值
- 值唯一性:每个键对应的值集合不允许重复
- 哈希实现:基于哈希表实现,提供高效查找
- 不可变/可变:不同实现库提供不同版本
2. 两种主要实现
1. Vavr 的不可变 HashMultimap
依赖:
<dependency>
<groupId>io.vavr</groupId>
<artifactId>vavr</artifactId>
<version>0.10.4</version>
</dependency>
基本使用:
import io.vavr.collection.HashMultimap;
// 创建空HashMultimap
HashMultimap<String, Integer> multimap = HashMultimap.withSeq().empty();
// 添加元素(返回新实例)
multimap = multimap.put("even", 2);
multimap = multimap.put("even", 4);
multimap = multimap.put("odd", 1);
multimap = multimap.put("odd", 3);
// 获取值
System.out.println(multimap.get("even")); // Seq(2, 4)
System.out.println(multimap.get("odd")); // Seq(1, 3)
2. Guava 的可变 HashMultimap
依赖引入:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
</dependency>
基本使用:
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
// 创建可变HashMultimap
Multimap<String, Integer> multimap = HashMultimap.create();
// 添加元素(直接修改)
multimap.put("even", 2);
multimap.put("even", 4);
multimap.put("odd", 1);
multimap.put("odd", 3);
// 获取值
System.out.println(multimap.get("even")); // [2, 4]
System.out.println(multimap.get("odd")); // [1, 3]
3. 核心操作详解
-
添加元素
// Vavr (不可变)
multimap = multimap.put("key", "value1");
multimap = multimap.put("key", "value2");
// Guava (可变)
multimap.put("key", "value1");
multimap.put("key", "value2");
2.获取元素
// 获取某个键的所有值
Iterable<String> values = multimap.get("key");
// 检查键是否存在
boolean containsKey = multimap.containsKey("key");
// 检查键值对是否存在
boolean containsEntry = multimap.containsEntry("key", "value1");
3. 移除元素
// Vavr
multimap = multimap.remove("key", "value1"); // 移除特定键值对
multimap = multimap.removeAll("key"); // 移除键的所有值
// Guava
multimap.remove("key", "value1");
multimap.removeAll("key");
4.遍历元素
// 遍历所有键值对
multimap.forEach((key, value) ->
System.out.println(key + ": " + value));
// 遍历所有键
for (String key : multimap.keys()) {
System.out.println("Key: " + key);
}
// 遍历所有值
for (String value : multimap.values()) {
System.out.println("Value: " + value);
}
4. 高级特性
1.不可变特性(Vavr)
// 原始map不会被修改
HashMultimap<String, String> original = HashMultimap.withSeq().empty();
HashMultimap<String, String> modified = original.put("k", "v");
System.out.println(original.size()); // 0
System.out.println(modified.size()); // 1
2.值集合视图(Guava)
// 获取键的视图集合
Collection<String> valuesView = multimap.get("key");
// 获取所有键的视图
Multiset<String> keys = multimap.keys();
// 获取所有键值对的视图
Collection<Map.Entry<String, String>> entries = multimap.entries();
5. 实际应用场景
1.分类存储
// 按部门存储员工
Multimap<String, Employee> deptEmployees = HashMultimap.create();
deptEmployees.put("IT", new Employee("Alice", 1001));
deptEmployees.put("IT", new Employee("Bob", 1002));
deptEmployees.put("HR", new Employee("Charlie", 1003));
2.反向索引
// 文档反向索引
Multimap<String, Document> invertedIndex = HashMultimap.create();
for (Document doc : documents) {
for (String keyword : doc.getKeywords()) {
invertedIndex.put(keyword, doc);
}
}
3.消息路由
// 消息处理器路由
Multimap<String, MessageHandler> handlers = HashMultimap.create();
handlers.put("order", new OrderCreatedHandler());
handlers.put("order", new OrderPaidHandler());
handlers.put("payment", new PaymentHandler());
// 分发消息
String messageType = "order";
for (MessageHandler handler : handlers.get(messageType)) {
handler.handle(message);
}