Search code examples
javajava-8functional-interface

Which FunctionalInterface should I use?


I was learning to write some lambda representation as FunctionalInterface. So, to add two integers I used:

BiFunction<Integer, Integer, Integer> biFunction = (a, b) -> a + b;
System.out.println(biFunction.apply(10, 60));

Gives me the output 70. But if I write it as this

BinaryOperator<Integer, Integer, Integer> binaryOperator = (a, b) -> a + b;

I get an error saying

Wrong number of type arguments: 3; required: 1

Isn't BinaryOperator a child of BinaryFunction? How do I improve it?


Solution

  • BinaryOperator

    Since BinaryOperator works on a single type of operands and result. i.e. BinaryOperator<T>.

    Isn't BinaryOperator a child of BinaryFunction?

    Yes. BinaryOperator does extends BiFunction. But do note the documentation states(formatting mine):

    This is a specialization of BiFunction for the case where the operands and the result are all of the same type.

    The complete representation is as:

    BinaryOperator<T> extends BiFunction<T,T,T>
    

    hence your code shall work with

    BinaryOperator<Integer> binaryOperator = (a, b) -> a + b;
    System.out.println(binaryOperator.apply(10, 60));
    

    IntBinaryOperator

    If you're supposed to be dealing with two primitive integers as currently in your example (add two integers I used), you can make use of the IntBinaryOperator FunctionalInterface as

    IntBinaryOperator intBinaryOperator = (a, b) -> a + b;
    System.out.println(intBinaryOperator.applyAsInt(10, 60));
    

    Represents an operation upon two int-valued operands and producing an int-valued result. This is the primitive type specialization of BinaryOperator for int.


    I am using Integer, can I still use IntBinaryOperator

    Yes, you can still use it but notice the representation of the IntBinaryOperator

    Integer first = 10;
    Integer second = 60;
    IntBinaryOperator intBinaryOperator = new IntBinaryOperator() {
        @Override
        public int applyAsInt(int a, int b) {
            return Integer.sum(a, b);
        }
    };
    Integer result = intBinaryOperator.applyAsInt(first, second); 
    

    would incur you an overhead of unboxing first and second to primitives and then autoboxing the sum as an output to result of type Integer.

    Note: Be careful of using null-safe values for the Integer though or else you would probably end up with a NullPointerException.