为什么Guava Multimap.values()返回一个平面集合而不是一个集合的集合?

13

我非常喜欢Google Guava库中的Multimap类。它是一种映射类型,您可以为一个键添加多个值,因此它有效地将一个键映射到某种类型的集合中。我特别喜欢的是Multimaps.index()函数,它接受一个Iterable和一个键函数,并返回一个Multimap,该函数通过函数返回每个元素的值来对Iterable的元素进行分组(索引或映射)。

我发现有点奇怪的是 Multimap.values() 返回的是一个平面集合而不是集合的集合?所以,一旦我检索了这些值,索引功能给我的分组就会丢失。我可以通过调用Multimap.asMap(),然后在其上调用values() 来解决这个问题。

有人知道为什么 Multimap 会这样表现吗?

2个回答

15

Multimap.asMap().values() 并不是解决问题的一种方式 -- Multimap 提供 两种 访问方式,通过 asMap().values() 获取一个 Collection<Collection<V>>,通过 values() 获取扁平化的 Collection<V>

更一般地说,Multimap 尝试着不仅仅是“映射到集合的映射”,而是“将键与多个值相关联的通用方法”。所以可以使用 entries() 方法除了 values()keys()asMap() 视图提供了将其作为“映射到集合的映射”的方法,但这具有非常不同的语义,这并不总是您要寻找的。

无论如何,values 方法只是旨在填补与 asMap().values() 不同的另一种需求。


分组是我通常使用Multimap的原因,所以我的“问题”是指我的领域问题,而不是Multimap-API的问题。不能听起来像是我在批评API。只是没有完全理解它背后的哲学。感谢您的回答。 - nansen
2
@nansen:Multimap并不是在试图隐藏这两个概念的重叠部分(例如,您始终可以通过keys()进行迭代,并执行get(key)以获取该键的值集合)。理解就是,如果您要求multimap中的所有值,则不关心相关的键,就像普通映射一样。对于所有其他情况,它都为您提供了一个实时视图,以将其视为Map<K,Collection<V>>。您知道asMap不会复制任何数据,对吧?它只是相同数据的不同视图,因此开销可以忽略不计。 - Mark Peters
1
我喜欢这种观点,因为它表达了可重用性的一个关键原则。就像Alan Perlis所说:“最好有100个函数操作一个数据结构,而不是10个函数操作10个数据结构。” - nansen
我们喜欢提供视图这一点确实是正确的 -- 这使得在许多不同的方式上操作相同的结构变得更加简单。 - Louis Wasserman

6

有人知道为什么Multimap会表现出这种行为吗?

多重映射应该被视为普通的映射,其中键不需要是唯一的。

Key       Val
 a   ->    1
 b   ->    2
 a   ->    3

Values: {1, 2, 3}

1
我认为你的意思是,一个普通的映射表不会将从values()返回的值与它们的键相关联(除了迭代顺序),那么为什么Multimap要背离这个惯例呢?如果是这样,我同意。 - Mark Peters
没错,这是另一种表达方式。 - aioobe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接