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