Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The signature of flatMap in Optional of Java 8

In the oracle docs, it appears to be

<U> Optional<U> flatMap(Function<? super T,Optional<U>> mapper)

For mapper as a Function, it makes the parameter contra-variant but does not make the return type covariant. I wonder if the mapper can (should) be

Function<? super T,Optional<? extends U>>

or

Function<? super T, ? extends Optional<? extends U>>

?

like image 975
huoenter Avatar asked Jan 06 '18 05:01

huoenter


People also ask

What is flatMap in optional Java?

Map. FlatMap. Map will apply the mapping function and if the result is not null – will return Optional describing the result. Flatmap will apply the mapping function and if the result is not null and result already being an optional – flatmap does not wrap with additional Optional.

How do you use flatMap in Java 8?

We can use a flatMap() method on a stream with the mapper function List::stream. On executing the stream terminal operation, each element of flatMap() provides a separate stream. In the final phase, the flatMap() method transforms all the streams into a new stream.

What is the use of optional class in Java 8?

Optional is a container object used to contain not-null objects. Optional object is used to represent null with absent value. This class has various utility methods to facilitate code to handle values as 'available' or 'not available' instead of checking null values.

What is the return type of flatMap?

The flatMap() method returns a new array formed by applying a given callback function to each element of the array, and then flattening the result by one level.


1 Answers

First of all, IMO, since U binds to the method itself but not the class Optional and also Optional is final, the current signature should work fine.

If either the two conditions above does not hold, then changes can be applied. Thanks for the link provided by @MalteHartwig. Let me summarize the answer to this particular question. It becomes clear that if the return type needs to be covariant, the latter signature (the longer one) is necessary in Java 8. It is not only about inheritance. ? extends is needed in front of Optional<? extends U> to declare the user-site variance of Function even when Optional is final. I made a code snippet to demonstrate it:

import java.util.function.Function;

class A {}
class B extends A {}

final public class Option<T> {
  private T value;
  public Option(T v) { value = v; }
  <U> Option<? extends U> flatMap1(Function<? super T, Option<? extends U>> mapper) {
    return mapper.apply(value);
  }

  <U> Option<? extends U> flatMap2(Function<? super T, ? extends Option<? extends U>> mapper) {
    return mapper.apply(value);
  }

  void test() {
    Option<A> oa = new Option<>(new A());
    Function<A,Option<A>> faa = (A a) -> new Option<>(new A());
    Function<A,Option<B>> fab = (A a) -> new Option<>(new B());
    //oa.flatMap1(faa);   DOES NOT COMPILE
    oa.flatMap2(fab);
  }
}

It seems that since Java only has user-site variance declaration, you may need a series of ? extends that propagate that declaration all the way to the (2nd) outermost level from the type variable you want to declare variance for.

like image 97
huoenter Avatar answered Nov 06 '22 17:11

huoenter