1. 概述
在这篇文章中,我们将探讨Google Guava库中的Multimap
实现。它是一种类似于java.util.Map
的集合,但每个键可以关联多个值。
2. Maven依赖
首先,我们添加一个依赖:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>32.1.3-jre</version>
</dependency>
最新版本可以在这里找到。
3. Multimap
实现
对于Guava的Multimap
,如果为同一个键添加两个值,第二个值不会覆盖第一个值,而是会在结果map
中保留两个值。让我们看一个测试用例:
String key = "a-key";
Multimap<String, String> map = ArrayListMultimap.create();
map.put(key, "firstValue");
map.put(key, "secondValue");
assertEquals(2, map.size());
打印map
的内容将输出:
{a-key=[firstValue, secondValue]}
当我们通过键“a-key”获取值时,我们会得到一个包含“firstValue”和“secondValue”的Collection<String>
:
Collection<String> values = map.get(key);
打印值将输出:
[firstValue, secondValue]
4. 与标准Map
比较
java.util
包中的标准Map
不允许我们将多个值分配给相同的键。考虑一个简单的案例,我们使用相同的键向Map
中添加两个值:
String key = "a-key";
Map<String, String> map = new LinkedHashMap<>();
map.put(key, "firstValue");
map.put(key, "secondValue");
assertEquals(1, map.size());
结果的map
只有一个元素(“secondValue”),因为第二次put()
操作覆盖了第一个值。如果我们想在Guava的Multimap
中实现相同的行为,我们需要创建一个Map
,其值类型为List<String>
:
String key = "a-key";
Map<String, List<String>> map = new LinkedHashMap<>();
List<String> values = map.get(key);
if(values == null) {
values = new LinkedList<>();
values.add("firstValue");
values.add("secondValue");
}
map.put(key, values);
assertEquals(1, map.size());
显然,这不是很方便。如果我们的代码中需要这种功能,那么Guava的Multimap
可能比java.util.Map
更合适。
这里需要注意的是,尽管列表中有两个元素,但size()
方法返回1。在Multimap
中,size()
返回存储在Map
中的实际值的数量,而keySet().size()
返回唯一键的数量。
5. Multimap
的优点
Multimap
通常用于需要Map<K, Collection<V>>
的地方。区别包括:
- 在添加条目之前不需要先填充空集合,使用
put()
即可 -
get()
方法永远不会返回null
,只会返回一个空集合(无需像Map<String, Collection<V>>
的测试用例那样检查null
) - 如果一个键映射至少有一个值,则该键存在于
Multimap
中。任何导致某个键关联值为零的操作都会删除该键(在Map<String, Collection<V>>
中,即使我们从集合中移除所有值,我们仍保留一个空的Collection
作为值,这是不必要的内存开销) - 可以通过
size()
获取总条目值的数量
6. 结论
本文展示了如何以及何时使用Guava的Multimap
。它将Multimap
与标准的java.util.Map
进行了比较,并突出了GuavaMultimap
的优势。
所有这些示例和代码片段可以在GitHub项目中找到——这是一个Maven项目,可以直接导入并运行,因为它已经配置好。