foreach/filter/map/reduce on Iterable & Iterators
Craig P. Motlin
cmotlin at gmail.com
Thu Sep 15 05:46:09 PDT 2011
It seems like it doesn't matter much, but sometimes that flexibility is
exactly what you need. Guava has the type signature I described [1]. And I
came to the same conclusion on a similar API. And as Maurizio said, it is
conceptually the correct type signature. Functions really are covariant in
their parameter type and contravariant in their return type.
Another way of looking at it - using wildcards this way may be unusual, but
it should work:
Mapper<? super MyType, ? extends MyOtherType> mapper = ...;
myTypes.map(mapper);
[1]
http://docs.guava-libraries.googlecode.com/git-history/v9.0/javadoc/com/google/common/collect/Iterables.html#transform(java.lang.Iterable,
com.google.common.base.Function)
On Thu, Sep 15, 2011 at 8:36 AM, Maurizio Cimadamore <
maurizio.cimadamore at oracle.com> wrote:
> 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