Java 8 – BinaryOperator and its primitive Functional Interface

In this article, we will discuss BinaryOperator Functional Interface which is sub-interface of BiFunction Functional Interface where,

  1. BiFunction Functional Interface – accepts 2-input arguments and a return-type of any data-type
  2. BinaryOperator Functional Interface – accepts 2-input arguments and a return-type of same data-type

In a way, it is very similar to BiFunction<T,U,R> Functional Interface except that both 2-input-arguments and return-type is same

1. BinaryOperator Functional Interface :

  • BinaryOperator accepts 2-input arguments whose data-type is same as that of return-type
  • This is very much similar to BiFunction Functional Interface
  • BinaryOperator<T> extends BiFunction<T, T, T> and inherits apply(); method from BiFunction Functional Interface
  • In Function<T, U, R> Functional Interface, we specify data-type for both 2-input arguments and return-type separately with comma in between them
  • Whereas in BinaryOperator<T> we specify only one type because this will be same for both 2-input arguments and return-type
  • Method signature: T apply(T value1, T value2); inherited from BiFunction Functional Interface
package java.util.function;

import java.util.Objects;
import java.util.Comparator;

@FunctionalInterface
public interface BinaryOperator<T> extends BiFunction<T,T,T> {

    // other default and static methods
}

1.1 Example for BinaryOperator Functional Interface :

  • We will look into 2 examples
  • 1st example – data-type is String which accepts 2 String values and returns concatenated string
  • 2nd example – data-type is Integer which accepts 2 number of primitive-type int and returns their sum (or addition)
package net.bench.resources.primitive.binaryoperator.example;

import java.util.function.BinaryOperator;

public class BinaryOperatorExample {

	public static void main(String[] args) {

		// 1. lambda expression to concatenate 2 strings using BinaryOperator FI
		BinaryOperator<String> bo1 = (s1, s2) -> s1.concat(s2);

		System.out.println("1. Concatenated String = " + bo1.apply("Bench", "Resources.Net"));


		// 2. lambda expression to add 2 numbers using BinaryOperator FI
		BinaryOperator<Integer> bo2 = (i1, i2) -> i1 + i2;

		System.out.println("\n2. 10 + 20 = " + bo2.apply(10, 20));
	}
}

Output:

1. Concatenated String = BenchResources.Net

2. 10 + 20 = 30

2. Primitive BinaryOperator Functional Interface :

  • This is very much similar to what we discussed above in BinaryOperator Functional Interface but it accepts 2 input arguments and return-type is always of primitive-type like int, long, double, etc. whereas BinaryOperator Functional Interface allows to accept any data-type
  • Performance-wise primitive BinaryOperator Functional Interface is much faster compared to BinaryOperator<T>
  • There are lot of conversion happening for auto-boxing & auto-unboxing for converting primitive-type to wrapper-type and again wrapper-type to primitive-type and so on
  • To avoid unnecessary conversion between primitive-type to wrapper-type and vice-versa, primitive-type specific BinaryOperator Functional Interface for conversion introduced in Java 1.8 version as listed below,
  1. IntBinaryOperator
  2. LongBinaryOperator
  3. DoubleBinaryOperator

We will look into method signature along with example for each one of the above mentioned Primitive BinaryOperator Functional Interface

2.1 IntBinaryOperator Functional Interface :

  • This primitive IntBinaryOperator Functional Interface accepts 2-input arguments and return-type of primitive-type int and it is not required to declare while defining IntBinaryOperator (or lambda expression)
  • Method signature: int applyAsInt(int left, int right);
package java.util.function;

@FunctionalInterface
public interface IntBinaryOperator {

    /**
     * Applies this operator to the given operands.
     *
     * @param left the first operand
     * @param right the second operand
     * @return the operator result
     */
    int applyAsInt(int left, int right);
}

2.1.1 Example for IntBinaryOperator Functional Interface :

  • Here, while defining lambda expression using IntBinaryOperator we haven’t specified any data-type like Integer for 2-input arguments and return-type, still compiler doesn’t complain and executed well
  • By default it will consider primitive-type int for both input arguments and return-type
package net.bench.resources.primitive.binaryoperator.example;

import java.util.function.IntBinaryOperator;

public class IntBinaryOperatorExample {

	public static void main(String[] args) {

		// lambda expression for multiplication of 2 numbers using IntBinaryOperator FI
		IntBinaryOperator ibo = (i1, i2) -> i1 * i2;

		// multiplication for below numbers
		System.out.println("1. 10 * 20 \t= " + ibo.applyAsInt(10, 20));

		System.out.println("2. 2 * 5 \t= " + ibo.applyAsInt(2, 5));

		System.out.println("3. 15 * 8 \t= " + ibo.applyAsInt(15, 8));

		System.out.println("4. 12 * 44 \t = " + ibo.applyAsInt(12, 44));

		System.out.println("5. 25 * 50 \t= " + ibo.applyAsInt(25, 50));
	}
}

Output:

1. 10 * 20 	= 200
2. 2 * 5 	= 10
3. 15 * 8 	= 120
4. 12 * 44 	 = 528
5. 25 * 50 	= 1250

2.2 LongBinaryOperator Functional Interface :

  • This primitive LongBinaryOperator Functional Interface accepts 2-input arguments and return-type of primitive-type long and it is not required to declare while defining LongBinaryOperator (or lambda expression)
  • Method signature: long applyAsLong(long left, long right);
package java.util.function;

@FunctionalInterface
public interface LongBinaryOperator {

    /**
     * Applies this operator to the given operands.
     *
     * @param left the first operand
     * @param right the second operand
     * @return the operator result
     */
    long applyAsLong(long left, long right);
}

2.2.1 Example for LongBinaryOperator Functional Interface :

  • Here, while defining lambda expression using LongBinaryOperator we haven’t specified any data-type like Long for 2-input arguments and return-type, still compiler doesn’t complain and executed well
  • By default it will consider primitive-type long for both input arguments and return-type
package net.bench.resources.primitive.binaryoperator.example;

import java.util.function.LongBinaryOperator;

public class LongBinaryOperatorExample {

	public static void main(String[] args) {

		// lambda expression for addition of 2 numbers using LongBinaryOperator FI
		LongBinaryOperator lbo = (l1, l2) -> l1 + l2;

		// multiplication for below numbers
		System.out.println("1. 10125 + 20123 = " + lbo.applyAsLong(10125, 20123));

		System.out.println("2. 21478 + 52589 = " + lbo.applyAsLong(21478, 52589));

		System.out.println("3. 15321 + 82365 = " + lbo.applyAsLong(15321, 82365));

		System.out.println("4. 12125 + 44256 = " + lbo.applyAsLong(12125, 44256));

		System.out.println("5. 25785 + 50125 = " + lbo.applyAsLong(25785, 50125));
	}
}

Output:

1. 10125 + 20123 = 30248
2. 21478 + 52589 = 74067
3. 15321 + 82365 = 97686
4. 12125 + 44256 = 56381
5. 25785 + 50125 = 75910

2.3 DoubleBinaryOperator Functional Interface :

  • This primitive DoubleBinaryOperator Functional Interface accepts 2-input arguments and return-type of primitive-type double and it is not required to declare while defining DoubleBinaryOperator (or lambda expression)
  • Method signature: double applyAsDouble(double left, double right);
package java.util.function;

@FunctionalInterface
public interface DoubleBinaryOperator {
    /**
     * Applies this operator to the given operands.
     *
     * @param left the first operand
     * @param right the second operand
     * @return the operator result
     */
    double applyAsDouble(double left, double right);
}

2.3.1 Example for DoubleBinaryOperator Functional Interface :

  • Here, while defining lambda expression using DoubleBinaryOperator we haven’t specified any data-type like Double for 2-input arguments and return-type, still compiler doesn’t complain and executed well
  • By default it will consider primitive-type double for both input arguments and return-type
package net.bench.resources.primitive.binaryoperator.example;

import java.util.function.DoubleBinaryOperator;

public class DoubleBinaryOperatorExample {

	public static void main(String[] args) {

		// lambda expression for subtraction of 2 double numbers using DoubleBinaryOperator FI
		DoubleBinaryOperator dbo = (d1, d2) -> d1 - d2;

		// multiplication for below numbers
		System.out.println("1. 20.123 - 10.125 = " + dbo.applyAsDouble(20.123, 10.125));

		System.out.println("2. 525.89 - 214.78 = " + dbo.applyAsDouble(525.89, 214.78));

		System.out.println("3. 823.65 - 153.21 = " + dbo.applyAsDouble(823.65, 153.21));

		System.out.println("4. 44.256 - 12.125 = " + dbo.applyAsDouble(44.256, 12.125));

		System.out.println("5. 5.0125 - 2.5785 = " + dbo.applyAsDouble(5.0125, 2.5785));
	}
}

Output:

1. 20.123 - 10.125 = 9.998000000000001
2. 525.89 - 214.78 = 311.11
3. 823.65 - 153.21 = 670.4399999999999
4. 44.256 - 12.125 = 32.131
5. 5.0125 - 2.5785 = 2.434

References:

Happy Coding !!
Happy Learning !!

Java 8 - Method and Constructor References
Java 8 - UnaryOperator and its primitive Functional Interface