我有一个带有以下签名的方法:
public <T> int numberOfValues(Map<T, Set<?>> map)
但我不能称它在Map<String, Set<String>>
中传递。例如,以下内容无法编译:
Map<String, Set<String>> map = new HashMap<>();
numberOfValues(map);
错误信息是:
numberOfValues (java.util.Map<java.lang.String,java.util.Set<?>>) in class cannot be applied to (java.util.Map<java.lang.String,java.util.Set<java.lang.String>>)
但是,如果我改为以下一切都很好:
public <T, V> int numberOfValues(Map<T, Set<V>> map)
但是我对V
一点都不感兴趣,因为我只是想知道每个集的大小。
为了完整起见,这是整个方法:
public <T, V> int numberOfValues(Map<T, Set<V>> map) {
int n = 0;
for (T key : map.keySet()) {
n += map.get(key).size();
}
return n;
}
我知道它也可以像这样完成,但不是问题的重点:)
public <T> int numberOfValues(Map<?, Set<T>> map) {
int n = 0;
for (Set<T> value : map.values()) {
n += value.size();
}
return n;
}
更新:另一种实现相同的方法
public <T> int numberOfValues(Map<?, Set<T>> map) {
int n = 0;
for (Object key : map.keySet()) {
n += map.get(key).size();
}
return n;
}
最终更新 感谢Jorn的回答,这是最终的实施......
public int numberOfValues(Map<?, ? extends Set<?>> map) {
int n = 0;
for (Set<?> value : map.values()) {
n += value.size();
}
return n;
}
答案 0 :(得分:10)
您错过了Set<?>
也用作通用参数的事实。而泛型是不变的。即,当参数为Map<String, Set<?>>
时,传递的参数必须精确为Map<String, Set<?>
(或子类型)。而使用Set<V>
推断出类型参数。
您可以使用有界通配符来解决此问题:
public <T> int numberOfValues(Map<T, ? extends Set<?>> map) {
...
}
答案 1 :(得分:0)
提示:
在numberOfValues
方法中,编写类似
Set<Object> set = new HashSet<>();
set.add(1);
set.add("Powned");
map.put(null, set);
您可以使用地图中已有的合适的密钥替换null
以进行有效的映射,从而彻底打破周围代码中的类型安全性。
推断或明确定义集合的类型,或添加通配符绑定以防止变异地图访问(如? extends Set<?>
)