我需要对包含选项的两个大小数执行添加操作:
var myURL: URL = NSURLComponents().url!
我想实现ordersTotal + = newOrder 重要的是要注意,如果两个值都为空,则结果同样应为空(即不为零)。
以下是我提出的建议:
Optional<BigDecimal> ordersTotal;
Optional<BigDecimal> newOrder;
但我想知道是否有更优雅的解决方案。
答案 0 :(得分:12)
我认为在选项上使用流或方法链的建议答案非常聪明,但也许是如此模糊以至于模糊不清。 OP已将其建模为ordersTotal += newOrder
,但如果两者都为空,则结果应为空而不是零。也许编写代码是合理的,因为它说:
if (!ordersTotal.isPresent() && !newOrder.isPresent()) {
result = Optional.empty();
} else {
result = Optional.of(ordersTotal.orElse(ZERO).add(newOrder.orElse(ZERO)));
}
虽然这不是最短的,但它清楚地表达了OP要求的内容。
现在我已将计算值分配给result
,但OP实际上想将其分配回ordersTotal
。如果我们都知道它们都是空的,那么我们就可以跳过将空指定给ordersTotal
的then子句。这样做,然后反转条件会更简单:
if (ordersTotal.isPresent() || newOrder.isPresent()) {
ordersTotal = Optional.of(ordersTotal.orElse(ZERO).add(newOrder.orElse(ZERO)));
}
现在,这往往会掩盖两个空的特殊情况,这可能不是一个好主意。另一方面,这表示&#34;如果其中任何一个非空,则添加值#34;这可能对应用程序有很大意义。
答案 1 :(得分:7)
不确定你是否会认为它更优雅,但这里有一个替代方案:
ordersTotal = Optional.of(ordersTotal.orElse(BigDecimal.ZERO).add(newOrder.orElse(BigDecimal.ZERO)));
另一个,基于@user140547's suggestion:
ordersTotal = Stream.of(ordersTotal, newOrder)
.filter(Optional::isPresent)
.map(Optional::get)
.reduce(BigDecimal::add);
请注意,即使两个选项都为空,第一个版本也会返回Optional.of(BigDecimal.ZERO)
,而在这种情况下,第二个版本将返回Optional.empty()
。
答案 2 :(得分:1)
您可以使用选项流。然后你可以创建一个bigdecimals流,然后减少那些bigdecimals,否则返回0。
这样做的好处是,如果您想要执行两个以上的选项,则无需更改代码。
(如果需要,可以在以后添加代码,目前我无法访问计算机)
答案 3 :(得分:1)
请注意您的解决方案
ordersTotal=ordersTotal.flatMap(b -> Optional.of(b.add(newOrder.orElse(BigDecimal.ZERO))));
如果Optional
为空,将生成空ordersTotal
,即使newOrder
不是。
可以通过将其更改为
来解决此问题ordersTotal=ordersTotal
.map(b -> Optional.of(b.add(newOrder.orElse(BigDecimal.ZERO))))
.orElse(newOrder);
但我更喜欢
ordersTotal=ordersTotal
.map(b -> newOrder.map(b::add).orElse(b))
.map(Optional::of).orElse(newOrder);
答案 4 :(得分:1)
我知道这是一个老线程,但是这个怎么样?
,SUM(CASE WHEN ReceiptCode LIKE 'V.Ch%' THEN ReceiptAmount ELSE 0 END)
OVER (Partition by Receipt)
AS ChangeSpend
我对这种方法背后的想法是这样的:
在所有灵魂可选等的背后,这里的基本逻辑仍然是 orderTotal + = newOrder
在第一个newOrder存在之前,orderTotal不存在,在代码中由空的Optional表示。
答案 5 :(得分:0)
这里的Optional和Stream不能很好地融合在一起。
java 8中最好的是:
ordersTotaI = !ordersTotaI.isPresent() ? newOrder
: !newOrder.isPresent() ? ordersTotaI
: Optional.of(ordersTotaI.get().add(newOrder.get()));
然而,好消息是,java 9会为Optional添加一些不错的(也是丑陋的)功能。
答案 6 :(得分:0)
您的要求不是您的解决方案。空的Optional不是零,而是缺少值。您基本上要求5 + NaN等于5.可选的flatMap引导您走向快乐的道路:5 + Nan是Nan,这正是flatMap所做的。
答案 7 :(得分:0)
考虑到您想重新分配给ordersTotal
,您会注意到ordersTotal
仅在存在newOrder
时才会更改。
因此,您可以从该支票开始,并将其写为:
if (newOrder.isPresent()) {
ordersTotal = newOrder.map(ordersTotal.orElse(ZERO)::add);
}
(这可以看作是Stuart Marks' second solution的简化。在这种情况下,由于ordersTotal
并不是有效的最终形式,方法引用也不能转换回lambda)
如果通过此检查开始,还有另一种可能的“ 聪明”方法:
if (newOrder.isPresent()) {
ordersTotal = ordersTotal.map(o -> newOrder.map(o::add)).orElse(newOrder);
}
其中中间map()
返回一个Optional<Optional<BigDecimal>>
,其内部Optional
不能为空。由于可读性差,我不认为它是一个好的解决方案,因此,我建议选择第一个选项或Stuart的解决方案之一。