2017-02-13 871 views
10

我有一個構建列表的方法,我希望它將列表的平均值作爲可選值返回。將OptionalDouble轉換爲可選<java.lang.Double>

但是,當我使用Java 8計算平均值時,我總是將返回值作爲OptionalDouble獲取。

如何轉換

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

如何在OptionalDouble上獲得'getAsDouble',這將使你在'double'中得到平均值,這是你最終想要的。 – VHS

+3

一個OptionalDouble更高效;更接近'double',因此將使用代碼從'Optional '轉換爲'OptionalDouble'似乎會更好。但是,我認爲你知道這一點,並有你的理由。 –

+2

如果代碼構建如圖所示的列表,您已經知道它永遠不會是空的。那麼爲什麼要返回'Optional'呢? – Holger

回答

1

我不知道是否存在一個整潔的解決方案,但部份應該工作:

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

只是爲了好玩,我想看看它是否可以在單個語句書寫,而不需要任何一個OptionalDouble 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()); 

BTW,只是簡約的緣故,如果你會做靜態導入:

import static java.util.Optional.*; 

你可以省略Optional.,讓他有點少凌亂。

6

我會去這個方法:

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

順便說一句,我找到了另一種解決方案,它具有最簡單的形式。

我開始思考:當平均結果可以爲空時?只有列出它自己是空的,對吧?因此,如果我們確信列表不是空的,不是我們可以放心地做getAsDouble()

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

(從性能的角度來看,這可能是比創建額外的λ包裝更有效,因爲在類似的答案建議。)

+3

這是一個雙重測試,首先是'isEmpty()',然後是'ofNullable'中的'null'測試。沒有必要進行第二次測試:'return testList.isEmpty()?可選.empty():可選.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是一個空列表一個有效的返回值,而p可能完全跳過Optional