Преобразовать OptionalDouble в необязательный <java.lang.Double>

У меня есть метод, который создает список, и я хочу, чтобы он возвращал среднее значение списка как необязательное значение.

Однако, когда я вычисляю среднее значение с использованием Java 8, я всегда получаю возвращаемое значение как необязательный.

Как преобразовать

OptionalDouble to Optional<Double>?

Ниже приведен мой код для среднего расчета:

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


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

Спасибо.

Ответ 1

Я бы пошел на такой подход:

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

Ответ 2

Кстати, я нашел другое решение, которое имеет самую простую форму.

Я начал думать: когда результат среднего может быть пустым? Только когда список его сам пуст, не так ли? Поэтому, если мы уверены, что список не пуст, мы можем безопасно выполнить getAsDouble():

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

(с точки зрения производительности это может быть более эффективным, чем создание дополнительных лямбда-оберток, что было предложено в похожих ответах.)

Ответ 3

Небольшое отклонение от @Andremoniy answer заключается в пропуске DoubleStream и использовании коллектора averagingDouble():

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

Или рассмотрите, является ли 0 допустимым возвращаемым значением для пустого списка и, возможно, полностью пропустите Optional.

Ответ 4

Я не знаю, существует ли опрятное решение, но он должен работать:

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

Ответ 5

Просто для удовольствия, я хотел посмотреть, может ли он быть написан в одном заявлении, без какой-либо дополнительной переменной tempDouble. Вот лучшее, что я придумал:

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

Ответ 6

Я пришел к решению "одна строка" (одно выражение):

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

Кстати, только ради минимализма, если вы сделаете статический импорт:

import static java.util.Optional.*;

вы можете опустить Optional., что делает его немного менее грязным.