2017-02-13 869 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