java.util.function.BinaryOperator is a Functional Interface, it has only one abstract method.
It extends another Functional Interface java.util.function.BiFunction. It inherits apply and andThen methods from BiFunction, and adds two static factory methods maxBy and minBy.
BinaryOperator is special case of BiFunction, where all the parameter types and return type are of the same data-type.
This is how the method declaration looks like in this interface.
- R apply(T t, U u) :- R is the return type. T and U are parameter types. It takes two parameters and returns one value. But, in the case of BinaryOperator, T U and R are the same.
So, we can also write T apply(T p1, T p2) . - default <T> BiFunction<T, T, T> andThen(Function<? super T, ? extends T> afterProcessor) :- It is used for chaining new functions. The afterProcessor Function will be applied after the current BinaryOperator .
- static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) :- This returns a BinaryOperator, this BinaryOperator returns max among two inputs, and they are of data-type T. maxBy takes a comparator as it’s argument and returns a BinaryOperator as a result.
- static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator) :- This returns a BinaryOperator , this BinaryOperator returns min among two inputs, and they are of data type T. minBy takes comparator as it’s input and returns BinaryOperator.
In this article, we will go through these methods one by one.
This apply method implementation will take two integer value, it will raise one number to the power of the other.
We will provide four different implementations for this operation.
Class implementation :-
static class PowerOperatorClass implements BinaryOperator<Integer> { @Override public Integer apply(Integer num, Integer power) { return mathPower(num, power); } }
Anonymous class implementation :-
BinaryOperator<Integer> raiseUsingAnonymousClass = new BinaryOperator<Integer>(){ @Override public Integer apply(Integer num, Integer power) { return mathPower(num, power); } };
Lambda implementation :-
we explicitly mention the data-type of lambda parameters.
BinaryOperator<Integer> raiseByLambdaWithExplicitDataTypeMention = (Integer number, Integer pow) -> mathPower(number, pow);
We don’t mention the data-type and, we let the compiler do this job for us.
BinaryOperator<Integer> raiseBySimpleLambda = (number, pow) -> mathPower(number, pow);
We can pick any one of the implementations and use it, it will produce the same result.
We will use these two variables to run the code.
int numberToBeRaised = 100; int power = 5;
This is our utility function that does real job of raising to the power.
static int mathPower(Integer number, Integer power) { return number << power; }
I am using the smallest implementation from the list of above implementations.
int raisedValue = raiseBySimpleLambda.apply(numberToBeRaised, power); System.out.println(raisedValue);
And we get the following output.
3200
We will get the same result with other three implementations too.
Now, we will look into the andThen method.
We are going to use above implementations for this, in the above implementations a number ‘x’ is raised to a power of ‘y’, after that we will multiply that value by two then add 100 to it.
This is our lambda, which multiplies a number by 2.
Function<Integer, Integer> multiplyBy2 = (num) -> num * 2;
This is our lambda, which adds 100 to a number.
Function<Integer, Integer> add100 = (num) -> num + 100;
Let us chain these lambdas to get the desired result.
int finalValue = raiseBySimpleLambda .andThen(multiplyBy2) .andThen(add100) .apply(numberToBeRaised, power);
Output :-
6500
So, this is our BinaryOperator interface.
I only covered andThen and apply methods in this article. You can read maxBy and minBy methods here.
Complete Code :-
import java.util.function.BinaryOperator; import java.util.function.Function; import static java.lang.System.out; public class BinaryOperatorImplementation { public static void main(String ... args) { int numberToBeRaised = 100; int power = 5; BinaryOperator<Integer> raiseUsingAnonymousClass = new BinaryOperator<Integer>(){ @Override public Integer apply(Integer num, Integer power) { return mathPower(num, power); } }; BinaryOperator<Integer> raiseByLambdaWithExplicitDataTypeMention = (Integer number, Integer pow) -> mathPower(number, pow); BinaryOperator<Integer> raiseBySimpleLambda = (number, pow) -> mathPower(number, pow); out.println("#1 - Using Class Implementation."); PowerOperatorClass raiseToThePowerByClass = new PowerOperatorClass(); int raisedValue = raiseToThePowerByClass.apply(numberToBeRaised, power); out.println(raisedValue); out.println("#2 - Using anonymous class implementation"); raisedValue = raiseUsingAnonymousClass.apply(numberToBeRaised, power); out.println(raisedValue); out.println("#3 - Using Lambda with explicit type declaration"); raisedValue = raiseByLambdaWithExplicitDataTypeMention.apply(numberToBeRaised, power); out.println(raisedValue); out.println("#4 - Lambda without type declaration"); raisedValue = raiseBySimpleLambda.apply(numberToBeRaised, power); out.println(raisedValue); Function<Integer, Integer> multiplyBy2 = (num) -> num * 2; Function<Integer, Integer> add100 = (num) -> num + 100; int finalValue = raiseBySimpleLambda.andThen(multiplyBy2).andThen(add100).apply(numberToBeRaised, power); out.println("#5 And Then Final Value"); out.println(finalValue); } static int mathPower(Integer number, Integer power) { return number << power; } static class PowerOperatorClass implements BinaryOperator<Integer> { @Override public Integer apply(Integer num, Integer power) { return mathPower(num, power); } } }
Output :-
#1 - Using Class Implementation. 3200 #2 - Using anonymous class implementation 3200 #3 - Using Lambda with explicit type declaration 3200 #4 - Lambda without type declaration 3200 #5 And Then Final Value 6500