foreach/filter/map/reduce on Iterable & Iterators

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Thu Sep 15 05:36:25 PDT 2011


On 15/09/11 12:56, Colin Decker wrote:
> "? extends U" isn't necessary for map. All that allows is assigning what is
> really, say, an Iterable<Integer>  to Iterable<Number>  or Iterable<Object>
> without casting, which doesn't help anything.
>
I think they are referring to changing the signature of Collection.map 
(and other related methods) from this:

<U> Iterable<U> map(Mapper<T, U> mapper) ...

to this:

<U> Iterable<U> map(Mapper<? super T, ? extends U> mapper) ...

Now, while this case the '? extends' is conceptually correct, I kinda 
agree that the outcome won't be too different should the '? extends' be 
omitted. Since U is a method type-parameter (whose bound is Object - 
unrelated to T), that means that most of the times type-inference will 
be able to infer the right type for U; for example:

Mapper<Object, Object> moo;
Mapper<Number, Number> mnn;
Mapper<Integer, Integer> mii;

List<Integer> li = ...
li.map(moo) // U == Object
li.map(mnn) // U == Number
li.map(mii) // U == Integer

The above will work regardless of whether you put the '? extends' 
wildcard or not. Where things will be different is when type-parameters 
are explicitly specified:

li.<Object>map(mii) // ok with wildcards / error w/o wildcards (U == Object)
li.<Number>map(mii) // ok with wildcards / error w/o wildcards (U == Number)

Note that the above pattern might be common if i.e. you want to assign 
the result of the map operation to a type that is less specific than the 
type of the mapper. I.e.

List<Object> lo = li.map(mii) // U == Integer, type-mismatch, 
List<Integer> not compatible with List<Object>
List<Object> lo = li.<Object>map(mii) // ok

Maurizio








More information about the lambda-dev mailing list