Java 8 – UnaryOperator and its primitive Functional Interface

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

  1. Function Functional Interface – accepts 1 input argument and a return-type of any data-type
  2. UnaryOperator Functional Interface – accepts 1-input argument and a return-type of same data-type

In a way, it is very similar to Function<T,R> Functional Interface except that both input-argument and return-type are same

1. UnaryOperator Functional Interface :

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

@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {

    // other default and static methods
}

1.1 Example for UnaryOperator Functional Interface :

  • We will look into 2 examples
  • 1st example – data-type is String where it accepts String and returns sub-string for 1st 3 characters
  • 2nd example – data-type is Integer where it accepts number and returns number multiplied by 19
package net.bench.resources.primitive.unaryoperator.example;

import java.util.function.UnaryOperator;

public class UnaryOperatorExample {

	public static void main(String[] args) {

		// 1. lambda expression to get 1st three character using UnaryOperator FI
		UnaryOperator<String> uos = s -> s.substring(0, 3);

		System.out.println("1. Sub-string = " + uos.apply("BenchResources.Net"));


		// 2. lambda expression for multiplication by 19 using UnaryOperator FI
		UnaryOperator<Integer> uoi = i -> i*19;

		System.out.println("2. 17 * 19 = " + uoi.apply(17));
	}
}

Output:

1. Sub-string = Ben
2. 17 * 19 = 323

2. Primitive UnaryOperator Functional Interface :

  • This is very much similar to what we discussed above in UnaryOperator Functional Interface but it accepts 1 input argument & return-type is always of primitive-type like int, longdouble, etc. whereas UnaryOperator Functional Interface allows to accept any data-type
  • Performance-wise primitive UnaryOperator Functional Interface is much faster compared to UnaryOperator<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 UnaryOperator Functional Interface for conversion introduced in Java 1.8 version as listed below
  1. IntUnaryOperator
  2. LongUnaryOperator
  3. DoubleUnaryOperator

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

2.1 IntUnaryOperator Functional Interface :

  • This primitive IntUnaryOperator Functional Interface accepts 1-input argument and return-type of primitivetype int and it is not required to declare while defining IntUnaryOperator (or lambda expression)
  • Method signature: int applyAsInt(int operand);
package java.util.function;

import java.util.Objects;

@FunctionalInterface
public interface IntUnaryOperator {

    /**
     * Applies this operator to the given operand.
     *
     * @param operand the operand
     * @return the operator result
     */
    int applyAsInt(int operand);
    
    // other default and static methods
}

2.1.1 Example for IntUnaryOperator Functional Interface :

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

import java.util.function.IntUnaryOperator;

public class IntUnaryOperatorExample {

	public static void main(String[] args) {

		// lambda expression to get square value using IntUnaryOperator FI
		IntUnaryOperator iuo = i -> i*i;

		// testing/calculating square for above lambda expression with below numbers
		System.out.println("1. Square of 2 is = " + iuo.applyAsInt(2));

		System.out.println("2. Square of 19 is = " + iuo.applyAsInt(19));

		System.out.println("3. Square of 37 is = " + iuo.applyAsInt(37));

		System.out.println("4. Square of 15 is = " + iuo.applyAsInt(15));

		System.out.println("5. Square of 20 is = " + iuo.applyAsInt(20));
	}
}

Output:

1. Square of 2 is = 4
2. Square of 19 is = 361
3. Square of 37 is = 1369
4. Square of 15 is = 225
5. Square of 20 is = 400

2.2 LongUnaryOperator Functional Interface :

  • This primitive LongUnaryOperator Functional Interface accepts 1-input argument and return-type of primitivetype long and it is not required to declare while defining LongUnaryOperator (or lambda expression)
  • Method signature: long applyAsLong(long operand);
package java.util.function;

import java.util.Objects;

@FunctionalInterface
public interface LongUnaryOperator {

    /**
     * Applies this operator to the given operand.
     *
     * @param operand the operand
     * @return the operator result
     */
    long applyAsLong(long operand);
    
    // other default and static methods
}

2.2.1 Example for LongUnaryOperator Functional Interface :

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

import java.util.function.LongUnaryOperator;

public class LongUnaryOperatorExample {

	public static void main(String[] args) {

		// lambda expression to get cube value using LongUnaryOperator FI
		LongUnaryOperator luo = l -> l*l*l;

		// testing/calculating cube for above lambda expression with below numbers
		System.out.println("1. Cube of 2 is = " + luo.applyAsLong(2l));

		System.out.println("2. Cube of 19 is = " + luo.applyAsLong(19l));

		System.out.println("3. Cube of 37 is = " + luo.applyAsLong(37l));

		System.out.println("4. Cube of 15 is = " + luo.applyAsLong(15l));

		System.out.println("5. Cube of 20 is = " + luo.applyAsLong(20l));
	}
}

Output:

1. Cube of 2 is = 8
2. Cube of 19 is = 6859
3. Cube of 37 is = 50653
4. Cube of 15 is = 3375
5. Cube of 20 is = 8000

2.3 DoubleUnaryOperator Functional Interface :

  • This primitive DoubleUnaryOperator Functional Interface accepts 1-input argument and return-type of primitivetype double and it is not required to declare while defining DoubleUnaryOperator (or lambda expression)
  • Method signature: double applyAsDouble(double operand);
package java.util.function;

import java.util.Objects;

@FunctionalInterface
public interface DoubleUnaryOperator {

	/**
	 * Applies this operator to the given operand.
	 *
	 * @param operand the operand
	 * @return the operator result
	 */
	double applyAsDouble(double operand);

	// other default and static methods
}

2.3.1 Example for DoubleUnaryOperator Functional Interface :

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

import java.util.function.DoubleUnaryOperator;

public class DoubleUnaryOperatorExample {

	public static void main(String[] args) {

		// lambda expression to get square value using DoubleUnaryOperator FI
		DoubleUnaryOperator duo = d -> d*d;

		// testing/calculating square for above lambda expression with below numbers
		System.out.println("1. Square of 2.5 is = " + duo.applyAsDouble(2.5));

		System.out.println("2. Square of 7.1 is = " + duo.applyAsDouble(7.1));

		System.out.println("3. Square of 3.7 is = " + duo.applyAsDouble(3.7));

		System.out.println("4. Square of 1.2 is = " + duo.applyAsDouble(1.2));

		System.out.println("5. Square of 9.3 is = " + duo.applyAsDouble(9.3));
	}
}

Output:

1. Square of 2.5 is = 6.25
2. Square of 7.1 is = 50.41
3. Square of 3.7 is = 13.690000000000001
4. Square of 1.2 is = 1.44
5. Square of 9.3 is = 86.49000000000001

References:

Happy Coding !!
Happy Learning !!

Java 8 - BinaryOperator and its primitive Functional Interface
Java 8 - Primitive Supplier Functional Interface