2017-02-13 17 views
10

У меня есть метод, который строит список, и я хочу, чтобы он возвращал среднее значение списка как необязательное значение.Convert OptionalDouble to Optional <java.lang.Double>

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

Как конвертировать

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(); 
} 

Спасибо.

+2

Как насчет 'getAsDouble' на OptionDouble, который даст вам среднее значение в' double', которое вы, наконец, захотите. – VHS

+3

Дополнительный Double - более эффективный; ближе к 'double', поэтому преобразование используемого кода из опционального ' to 'OptionDouble' будет казаться лучше. Но тогда, я думаю, вы знаете это и имеете свою причину. –

+2

Если код строит список, как показано, вы уже знаете, что он никогда не будет пустым. Так зачем вообще возвращать «Факультативный»? – Holger

ответ

1

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

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

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

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

Я пришел к этому «одной строкой» (одного заявления) решение:

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

BTV, только ради минимализма, если вы будет делать статическую импорт:

import static java.util.Optional.*; 

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

6

Я бы для такого подхода:

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

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

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

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

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

+3

Это двойной тест, первый 'isEmpty()', а затем тест 'null' в' fromNullable'. Второе испытание не требуется: 'return testList.isEmpty()? Optional.empty(): Optional.of (testList.stream(). MapToDouble (v -> v) .average(). GetAsDouble()); ' – Holger

+3

Я подумал об этом, но я специально поставил тройную операцию внутри' Необязательно. ofNullable'. Это более стильная вещь, хотя я согласен, что она имеет еще одну операцию сравнения – Andremoniy

4

небольшое изменение на @Andremoniy's answer, чтобы пропустить DoubleStream и использовать averagingDouble() коллектор:

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^