I have this function:
/**
* Helper function that adds the values of b to the elements of a, treating
* all keys that exist in b but not in a, as existent in a with value 0. NB:
* It operates IN PLACE.
* @param a The {@link java.util.Map} which will hold the result
* @param b The {@link java.util.Map} which will be added to a
*/
private static void sumMaps(Map<?, Integer> a, Map<?,Integer> b)
{
for (Object key : b.keySet()) {
Integer currentCount = a.get(key);
a.put(key, currentCount == null ? b.get(key) : currentCount + b.get(key));
}
}
However, NetBeans highlights "key" in the final line of for, and gives me this error:
method put in class java.util.Map<K,V> cannot be applied to given types
required: capture #67 of?, java.lang.Integer
found: java.lang.Object, int
(the int is not the problem because of Java unpacking, I tried using Integers too but it didn't work).
The problem is one of covariance. When you pull a key out of one map you cannot guarantee that the key is compatible with the other map. If one map uses Foos and the other map uses Bars and these two classes are unrelated to each other then you cannot interchange them.
Imagine that a is of type Map<String, Integer> and b is of type Map<Float, Integer>. These two types are compatible with your parameter declarations, but their key types are incompatible. You will have trouble if you take a Float from b and try to use it as a key in a.put(key,...). That is effectively what the compiler is complaining about. Using ? does not restrict the maps to compatible key types.
Instead of ? you must specify that the two key classes are the same by setting them both to some generic Key class. This way the keys from one map can be inserted into the keys from the other map.
private static <Key> void sumMaps(Map<Key, Integer> a, Map<Key, Integer> b)
{
for (Key key : b.keySet()) {
Integer currentCount = a.get(key);
a.put(key, currentCount == null ? b.get(key) : currentCount + b.get(key));
}
}
Generally speaking, if you're trying to suss out a problem with ?, do not mentally replace ? with Object. Instead, a better way to think about it is to replace every instance of ? with a different imaginary type name.
Warning: Math Analogy
It's similar to the C constant that shows up in indefinite integrals in calculus. For instance, ∫ cos x dx = sin x + C. If you do one integral then writing C is fine, but if you do multiple integrals then you have to remember that these constants are different and are not interchangeable. It then behooves you to write C1, C2, C3, etc.
? is the same way. The first time it shows up, pretend it is class A. The next time it is class B. And so on.
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