Filtering min of Optional values

2.4k views Asked by At

I want to get the minimum value of a function result of an object list. But the return value of this function is optional. So it would be OK if no fragment time is set so far and the return value should then be Optional.empty()

public Optional<Double> getFragmentTime(int fragment) {
    ...
}

private List<Entry> entries; // will be filled in the ctor.

public Optional<Double> getMinFragmentTime(int fragment) {
    return entries.stream()
       .map(e -> e.getFragmentTime(fragment))
       .filter(Optional::isPresent)
       .map(Optional::get)
       .min(Double::compare);
}

Is this the correct way to archive it? The two function calls .filter(Optional.isPresent) and .map(Optional.get) seems rather odd to me, and I think there must be a better solution for it.

2

There are 2 answers

0
Joop Eggen On

First one should use the stream for the primitive type, as that has a nice support for min().

public OptionalDouble getFragmentTime(int fragment) {
    ...
}

public OptionalDouble getMinFragmentTime(int fragment) {
    return entries.stream()
       .flatMap(e -> e.getFragmentTime(fragment).stream())
       .min();
}

An OptionalDouble may deliver a stream of 1 or 0 doubles. A flatMap to DoubleStream, and then taking the min.

(Code not verified.)

8
Nikolas Charalambidis On

You can use the advantage of flat-mapping with Optional::stream available since :

return entries.stream()                         // Stream<Entry>
        .map(e -> e.getFragmentTime(fragment))  // Stream<Optional<Double>>
        .flatMap(Optional::stream)              // Stream<Double>
        .min(Double::compare);                  // Optional<Double>

Note that .min(Double.compare); is not correct usage, the parameter is in fact the lambda expression ((d1, d2) -> Double.compare(d1, d2) which shall be shortened as method reference Double::compare. Also using Comparator.comparingDouble(d -> d) is possible.

In case of you have to stick with .filter(Optional::isPresent).map(Optional::get).