Let's start with a simple HashMap of Strings to Doubles as below and put in some values.
Map<String, Double> map = new HashMap<>();
map.put("one", 1.0);
map.put("two", 2.0);
map.put("three", 3.0);
Finding the sum using Java 8 lambdas is pretty straight forward
double sum = map.entrySet().stream().mapToDouble
(e->e.getValue()).sum();
or using method references
double sum = map.entrySet().stream().mapToDouble
(Map.Entry::getValue).sum();
What if you wanted to do the same thing for a map of String to BigDecimals?
Not being from a functional background my first instinct (based on the example above) was to do this:
Map<String, BigDecimal> map = new HashMap<>();
map.put("one", BigDecimal.ONE);
map.put("two", BigDecimal.valueOf(2));
map.put("three", BigDecimal.valueOf(3));
BigDecimal sum = BigDecimal.valueOf(map.entrySet().stream().mapToDouble(e->e.getValue().doubleValue()).sum());//DON'T DO THIS!!
This code is hideous, not to mention wrong because you are not actually using the add
method of the BigDecimal which might be important especially if you are multiplying and
dividing the values in the stream.
The correct way to sum this stream of BigDecimals is to use the map reduce pattern:
BigDecimal sum = map.entrySet().stream().map
(e->e.getValue()).reduce(BigDecimal.ZERO, BigDecimal::add);
This is much more elegant. It does exactly what you want by using the method add on
the BigDecimal and not just re-creating a BigDecimal after doing the work on doubles.
Why not
ReplyDeletemap.values().stream().reduce...