I was looking at the stream interface and found this method :
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
I can't find any reason why "? extends R" instead of R :
<R> Stream<R> map(Function<? super T, R> mapper);
so what will be the difference if I make it like above ? isn't the "?" is the R variable that I pass ? and it will extend R I can't find a reason for it.
It uses ? extends R
to allow functions taken by map
to be declared as returning a subtype of R
For example, given this stream:
Stream<Number> numberStream = Stream.of(1, 2L);
In the following map
call, R
is Number
, but the function is of type Function<Number, Integer>
:
Function<Number, Integer> function = n -> Integer.valueOf(n.intValue());
Stream<Number> numberStream2 = numberStream.map(function); //would have failed
If it did not take ? extends R
, then function
would have been an invalid argument (Function<Number, Number>
would have been required)
? extends R
means you can pass an object whose class is derived by R
, a.k.a subclass of R
.
So the map function can produce R
and R's subclass
as result. That is reasonable.
For example, If we have these classes:
Animal
, Groose (extends Animal)
, Egg
Function<Egg, Groose> hatching
You can write this code:
List<Egg> eggs = getEggs();
List<Animal> myPets = eggs.stream().map(hatching)....
You can see that your map
function requires Animal
type (R
), but your mapper returns Groose
type (which is ? extends R
). If the map
function writes as <R> Stream<R> map(Function<? super T, R> mapper);
, you have to add another conversion from Groose
to Animal
.
You can refer to this answer and understand <? extends T>
.
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