I have a method with the following signature:
public <T> int numberOfValues(Map<T, Set<?>> map)
However I can’t call it passing in a Map<String, Set<String>>
. For instance, the following doesn’t compile:
Map<String, Set<String>> map = new HashMap<>();
numberOfValues(map);
The error message being that:
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>>)
However, if I change to the following all is fine:
public <T, V> int numberOfValues(Map<T, Set<V>> map)
However I’m not at all interested in V
, as I just want to know the size of each of the sets.
For completeness sake, this is the whole method:
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;
}
Which I’m aware it can also be accomplished like this, but isn’t the point of the question :)
public <T> int numberOfValues(Map<?, Set<T>> map) {
int n = 0;
for (Set<T> value : map.values()) {
n += value.size();
}
return n;
}
Update: yet another way of achieving the same
public <T> int numberOfValues(Map<?, Set<T>> map) {
int n = 0;
for (Object key : map.keySet()) {
n += map.get(key).size();
}
return n;
}
Final update: Thanks to Jorn’s answer, this is the final implementation...
public int numberOfValues(Map<?, ? extends Set<?>> map) {
int n = 0;
for (Set<?> value : map.values()) {
n += value.size();
}
return n;
}
You're missing the fact that Set<?>
is also used as a generic parameter. And generics are invariant. i.e. when the parameter is Map<String, Set<?>>
, the passed argument must be exactly Map<String, Set<?>
(or a subtype of). Whereas with Set<V>
the type argument is inferred.
You can solve this by using a bounded wildcard:
public <T> int numberOfValues(Map<T, ? extends Set<?>> map) {
...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With