Search code examples
javalambdajava-8java-streamfunctional-interface

Why it works: BigDecimal Sum with Reduce and BigDecimal::add


I can understand why Total1 is calculated, but as Total2 is calculated I have no idea! How can a BigDecimal::add be used in a BiFunction? Signatures are not the same !!!

package br.com.jorge.java8.streams.bigdecimal;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class BigDecimalSumTest {
    public static void main(String[] args) {

        List<BigDecimal> list = new ArrayList<>();

        list.add(new BigDecimal("1"));
        list.add(new BigDecimal("2"));

        BigDecimal total1 = list.stream().reduce(BigDecimal.ZERO, (t, v) -> t.add(v));

        BigDecimal total2 = list.stream().reduce(BigDecimal.ZERO, BigDecimal::add);

        System.out.println("Total 1: " + total1);
        System.out.println("Total 2: " + total2);
    }
}

Solution

  • Its used as a BinaryOperator<T> in your current context.

    Its equivalent lambda representation:

    (bigDecimal, augend) -> bigDecimal.add(augend) // same as in your previous line of code
    

    and anonymous class representation:

    new BinaryOperator<BigDecimal>() {
        @Override
        public BigDecimal apply(BigDecimal bigDecimal, BigDecimal augend) {
            return bigDecimal.add(augend);
        }
    }
    

    where BinaryOperator<T> extends BiFunction<T,T,T>, meaning its a specialization of BiFunction for the case where the operands and the result are all of the same type.

    Added to that, your code is actually using one of the overloaded implementations of reduce method i.e. Stream.reduce(T identity, BinaryOperator<T> accumulator).


    How can a BigDecimal::add be used in a BiFunction

    Just a step further and only for explanation, there is also an overloaded implementation that uses combiner as in Stream.reduce​(U identity, BiFunction<U,​? super T,​U> accumulator, BinaryOperator<U> combiner) which would look like :

    BigDecimal total = list.stream()
                           .reduce(BigDecimal.ZERO, BigDecimal::add, BigDecimal::add);
    //                                                   ^^                ^^
    //                                              BiFunction here    BinaryOperator here