Python's `sum()` works only on numbers and assumes an empty list sums to 0. Java's `reduce()` is quite a bit more flexible.
I use Joda Money and frequently find myself doing:
final Money bucks = stream.map(Thing::getPrice).reduce(Dollars.ZERO, Money::plus);
If you don't pass in a baseline, you get optional:
final Optional<Money> bucks = stream.map(Thing::getPrice).reduce(Money::plus);
Also, StreamEx improves the ergonomics of Java streams. The way I would implement the original example:
EntryStream.of(cart.getProducts())
.mapKey(Product::getPrice)
.mapValue(BigDecimal::new)
.mapKeyValue(BigDecimal::multiply)
.reduce(BigDecimal.ZERO, BigDecimal::add);
Unfortunately BigDecimal is not especially ergonomic (it could use a `multiply(long)` method, which would eliminate the annoying `mapValue()` above). But unlike the python version of this, it will preserve scale. And streams work as-is on Money types.