简体   繁体   中英

Convert OptionalDouble to Optional <java.lang.Double>

I have a method that builds a list and I want it to return the average of the list as an Optional value.

However, when I calculate the average value using Java 8, I always get the return value as an OptionalDouble.

How do I convert

OptionalDouble to Optional<Double>?

Below are my code for average calculation:

private static Optional<Double> averageListValue() {
     // Build list
     List<Double> testList = new ArrayList<>();
     testList.add(...);
     ...
     ...


     return testList.stream().mapToDouble(value -> value).average();
}

Thanks.

I'd go for this approach:

private static Optional<Double> convert(OptionalDouble od) {
    return od.isPresent() ? 
        Optional.of(od.getAsDouble()) : Optional.empty();
}

A slight variation on @Andremoniy's answer is to skip the DoubleStream and use the averagingDouble() collector:

if (testList.isEmpty()) {
    return Optional.empty();
}
return Optional.of(testList.stream().collect(Collector.averagingDouble()));

Or consider whether 0 is a valid return value for an empty list, and possibly skip the Optional entirely.

BTW, I found another solution, which has most simple form.

I've started thinking about: when result of average can be empty? Only when list it self is empty, right? So if we are sure that list is not empty, than we can safely do getAsDouble() :

return Optional.ofNullable(testList.isEmpty() ? null : 
        testList.stream().mapToDouble(v -> v).average().getAsDouble())

(from performance point of view this could be more efficient than creating additional lambda wrappers, as was suggested in similar answers.)

This is quite an old question, but in newer versions of Java you can:

// Given an OptionalDouble
var myOptionalDouble = OptionalDouble.of(3.0d);

// Convert to Optional<Double>
var myOptional = myOptionalDouble.stream().boxed().findFirst();

The reverse is similarly easy:

var myOptional = Optional.of(Double.valueOf(3.0d));

var myOptionalDouble = myOptional.stream().mapToDouble(t -> t).findFirst();

I don't know if there exists a neat solution, but ths should work:

OptionalDouble optionalDouble = testList.stream().mapToDouble(value -> value).average();
return Optional.ofNullable(optionalDouble.isPresent() ? optionalDouble.getAsDouble() : null);

Just for fun, I wanted to see if it could be written in a single statement, without any need for an OptionalDouble temp variable. Here is the best I came up with:

return testList.stream().collect(Collectors.collectingAndThen(
    Collectors.summarizingDouble(Double::doubleValue),
    stat -> Optional.ofNullable(stat.getCount()>0 ? stat.getAverage() : null)));

I came to this "one line" (single statement) solution:

    return ((Function<OptionalDouble, Optional<Double>>) od
            -> od.isPresent() ? Optional.of(od.getAsDouble()) : Optional.empty())
            .apply(testList.stream().mapToDouble(v -> v).average());

BTW, just for sake of minimalism, if you will do static import:

import static java.util.Optional.*;

you can omit Optional. , what makes it a little bit less messy.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM