I need to perform an add operation on two big decimals that are wrapped optionals:
Optional<BigDecimal> ordersTotal;
Optional<BigDecimal> newOrder;
I want to achieve ordersTotal += newOrder It's important to note that if both values are empty the result should likewise be empty (ie not zero).
Here is what I came up with:
ordersTotal = ordersTotal.flatMap( b -> Optional.of(b.add(newOrder.orElse(BigDecimal.ZERO))));
but I'm wondering if there's a more elegant solution.
I think the suggested answers of using streams or chains of methods on optionals are very clever, but perhaps so clever as to be obscure. The OP has modeled this as ordersTotal += newOrder
with the exception that if both are empty, the result should be empty instead of zero. Maybe it would be reasonable to write the code so that it says that:
if (!ordersTotal.isPresent() && !newOrder.isPresent()) {
result = Optional.empty();
} else {
result = Optional.of(ordersTotal.orElse(ZERO).add(newOrder.orElse(ZERO)));
}
While this isn't the shortest, it clearly expresses exactly what the OP asked for.
Now I've assigned the computed value to result
but the OP actually wanted to assign it back to ordersTotal
. If we know both are empty, we can then skip the then-clause that assigns empty to ordersTotal
. Doing that, and then inverting the condition gives something simpler:
if (ordersTotal.isPresent() || newOrder.isPresent()) {
ordersTotal = Optional.of(ordersTotal.orElse(ZERO).add(newOrder.orElse(ZERO)));
}
Now, this tends to obscure the both-empty special case, which might not be a good idea. On the other hand, this says "add the values if either is non-empty" which might make a lot of sense for the application.
Not sure if you'll consider it more elegant, but here's one alternative:
ordersTotal = Optional.of(ordersTotal.orElse(BigDecimal.ZERO).add(newOrder.orElse(BigDecimal.ZERO)));
Another, based on @user140547's suggestion:
ordersTotal = Stream.of(ordersTotal, newOrder)
.filter(Optional::isPresent)
.map(Optional::get)
.reduce(BigDecimal::add);
Note that the first version returns Optional.of(BigDecimal.ZERO)
even when both optionals are empty, whereas the second will return Optional.empty()
in such a case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With