Guava:将 Multimap 转换为通用超类型是否有效?

Guava: Is it valid to cast a Multimap to generic supertypes?

目前我正在实施 Multimap class 以允许使用 Multisets 进行重复。特别是,我正在研究 boolean putAll(Multimap<? extends K, ? extends V> multimap) 方法。

我想这样做:

Map<K, Collection<V>> map = ((Multimap<K, V>)multimap).asMap();

其中 asMap() 通常会 return a Map<? extends K, Collection<? extends V>>.

这是否有效(如果我不添加到地图,就不会抛出错误)?如果没有,我该如何解决?

不,它无效,原因与将 List<T> 转换为 List<Object> 无效的原因相同。

Multimap.asMap()returns一个视图,according to the documentation。这意味着

Multimap<K, V> multimap = ...;
Map<SuperOfK, SuperOfV> map = (<some cast>) multimap.asMap();
map.put(superOfK, superOfV);

应该更新多图。虽然这本身不会导致 ClassCastException,但执行类似迭代键的操作会:

for (K key : multimap.keys()) { }

因此,这样的类型转换是不安全的,因此被禁止。

当然,如果您的多图是不可变的,您就不会遇到这个问题 - 但通常这就是您不应该这样做的原因。并且说 "I won't add to the map" 对编译器来说还不够好——它不知道你不会。

其他人已经回答了你的具体问题,但我认为你问错了问题(并试图做一些你不应该做的事情)。

首先,我想问一下您为什么要自己实施 Multimap。您似乎可以避免这样做。

其次,您正在尝试使用 map.putAll(Map) 添加 MultimapasMap() 视图传递给您的 Multimap.putAll(Multimap) 实现。这几乎肯定是错误的,并且会违反 Multimap.putAll 的规范。 asMap() 视图中的 Collection 值是关联键值的每个实时视图,它们的内容将在多图更改时 更改。如果您将这些集合直接添加到 Map 中,您可能已经支持了您的 Multimap 实施,如果其他 Multimap 之后被修改,您的 Multimap 将最终改变。不仅如此,如果您的 Map?

中已经有该键的值,会发生什么情况?