4

I came across this question:

We're given a map interface:

interface MyMap<K,V>{
  public void put (K key, V value);
  public V get (K key);
  public boolean containsKey (K key);
}

We want to implement a method addToMyMap whose signature is (we need to fill in the missing parts (the dots):

void addToMyMap(MYMap<....> m, List<....> keys, .... newValue)

The method will scan the list of keys, and for every key if it doesn't exist in the map it'll add it with newValue as the value.

The implementation that was given as the answer was the following:

 public static <K,V> void addToMyMap (MyMap <? super K, ? super V> m, List<? extends K> keys, V newValue) 
 {
   for (K key: keys)
   {
      if (!m.containsKey(key))
      {
         m.put(key,newValue);
      }
   } 
}

I'm not entirely sure why this implementation is correct. How can the containsKey method work if it gets a subclass of K? Isn't it like searching for an Apple in a List<Fruit>? How would you even iterate over that list?

The same thing goes for the put method: How can it iterate over a map with many different types?

This might have to do with the implementation of the Map.

So maybe the real question is how does a map which contains many supertypes of K and V know to iterate over the Ks.

An example for calling this method would be:

MyMap <Number, Number> m = new MyMapImpl<Number,Number>();
m.put(new Integer (1) , new Float(7.2));
m.put (new Float(3.1), new Double(9.99));

List<Integer> lst = new List<Integer>();
lst.add(1); lst.add(2); lst.add(3);
Float f = new Float (55.5);
Util.addToMyMap (m,lst,f);

How can this map, which holds float and integer lookup a key which is of type float (in put and containsKey)?

I'd appreciate some explanation.

matanc1
  • 6,525
  • 6
  • 37
  • 57

1 Answers1

4

This is known as The Get and Put Principle: use an extends wildcard when you only get values out of a structure, use a super wildcard when you only put values into a structure, and don't use a wildcard when you both get and put.

How can this map, which holds float and integer lookup a key which is of type float (in put and containsKey)?

The quizzical phrase ? super K means that the destination Map may have elements of any type that is a super type of K. This is known as A lower bounded wildcard, which restricts the unknown type to be a specific type or a super type of that type.

For example, List<Integer> is more restrictive than List<? super Integer> because the former matches a list of type Integer only, whereas the latter matches a list of any type that is a supertype of Integer.


For your context's MyMap <Number, Number> m, it has the type of Number which is super type of both Integer and Float. So it can contain elements both of the type Integer and Float. Even Double too. As all of them are subtype of Number. Supertype instance can always reference the subtype.

Please, check out:

  1. Lower Bounded Wildcards
  2. Guidelines for Wildcard Use
Sage
  • 15,290
  • 3
  • 33
  • 38
  • So maybe my question should be: How does the `Map` implementation iterate over a subtype when it holds many different supertypes. – matanc1 Nov 22 '13 at 11:29
  • +1 for mentioning Naftalin and Wadler's `Get and Put Principle` in *Effective Java* Bloch offers the following mnemonic: `PECS` which stands for `producer-extends, consumer-super` – Nir Alfasi Nov 22 '13 at 11:33
  • @Shookie, I have updated the answer. You may have got the wrong idea about `? super K` – Sage Nov 22 '13 at 11:34
  • @alfasin, Thank you. I am actually whining about finding an online reference so that the OP can easily read the description but seems like i don't have any choice but to mention about the book – Sage Nov 22 '13 at 11:36
  • @Sage - I'm aware of what they both mean. I understand how they are used in the method but not how the Map will work since there is more than one type in it. I've updated the question for clarification. – matanc1 Nov 22 '13 at 11:45
  • @Shookie, thank you for your update. I have updated the answer too to be parallel with your question. Please check and ask me if any more clarification is needed – Sage Nov 22 '13 at 11:54