So, how to get outcome of this code using functional programming:
public static final List<BigDecimal> numbers = Arrays.asList(
new BigDecimal("15"), new BigDecimal("10"), new BigDecimal("17"),
new BigDecimal("30"), new BigDecimal("18"), new BigDecimal("23"),
new BigDecimal("5"), new BigDecimal("12") );
BigDecimal totalOfReducedNumbers = BigDecimal.ZERO;
for(BigDecimal number : numbers) {
if(number.compareTo(BigDecimal.valueOf(20)) > 0)
totalOfReducedNumbers =
totalOfReducedNumbers.add(number.multiply(BigDecimal.valueOf(0.9)));
}
System.out.println("Total of reduced numbers: " + totalOfReducedNumbers);
Which throws out "Total of reduced numbers: 47.7"
How to get the same outcome using functional programming tools like map(), reduce() etc?
By performing the same operations, first filter values (you only want values greater than 20). Then multiply those values by 0.9
and finally reduce the terms by performing addition. Like,
BigDecimal TWENTY = BigDecimal.valueOf(20);
BigDecimal POINT9 = BigDecimal.valueOf(0.9);
System.out.println("Total of reduced numbers: " + numbers.stream()
.filter(x -> x.compareTo(TWENTY) > 0)
.map(x -> x.multiply(POINT9)).reduce((a, b) -> a.add(b)).get());
Outputs (as requested)
Total of reduced numbers: 47.7
And, as suggested in the comments, we can further improve that with a method reference and using orElse
would be safer than a raw get()
. Like,
System.out.println("Total of reduced numbers: " + numbers.stream()
.filter(x -> x.compareTo(TWENTY) > 0)
.map(x -> x.multiply(POINT9))
.reduce(BigDecimal::add)
.orElse(BigDecimal.ZERO));
The for loop implementation is a typical "reduce" pattern (also known as "fold", "Aggregate" pattern in some other languages)
You're looking for filter
--> reduce
method:
BigDecimal reduce =
numbers.stream()
.filter(n -> n.compareTo(BigDecimal.valueOf(20)) > 0)
.reduce(BigDecimal.ZERO,
(a, b) -> a.add(b.multiply(BigDecimal.valueOf(0.9))));
You can further minimise the number of objects contructed by caching BigDecimal.valueOf(20)
and BigDecimal.valueOf(0.9)
as shown in @Elliot's answer i.e.:
BigDecimal TWENTY = BigDecimal.valueOf(20);
BigDecimal POINT9 = BigDecimal.valueOf(0.9);
BigDecimal reduce =
numbers.stream()
.filter(n -> n.compareTo(TWENTY) > 0)
.reduce(BigDecimal.ZERO,
(a, b) -> a.add(b.multiply(POINT9)));
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