Java 8 — Primitive Type Functional Interfaces | Code Factory

Code Factory
6 min readMay 7, 2020

--

Index Page : Link

Reference Link : Link

Donate : Link

What is the Need of Primitive Type Functional Interfaces?

1. Autoboxing :

  • Automatic conversion from primitive type to Object type by compiler is called autoboxing.

2. Autounboxing :

  • Automatic conversion from object type to primitive type by compiler is called autounboxing.

3. In the case of generics, the type parameter is always object type and no chance of passing primitive type.

ArrayList<Integer> l = new ArrayList<Integer>(); // valid
ArrayList<int> l = new ArrayList<int>(); // invalid

Need of Primitive Functional Interfaces :

In the case of normal Functional interfaces (like Predicate, Function etc) input and return types are always Object types. If we pass primitive values then these primitive values will be converted to Object type (Auboxing), which creates performance problems.

package com.codeFactory.primitiveFunctional;import java.util.function.Predicate;public class Test {
public static void main(String... args) {
int x[] = {0, 5, 10, 15, 20};
Predicate<Integer> p = i -> i%2 == 0;
for(int x1 : x) {
if(p.test(x1)) {
System.out.println(x1);
}
}
}
}

Output :

0
10
20

In the above examples, 5 times autoboxing and autounboxing happening which creates performance problems.

To overcome this problem primitive functional interfaces introduced, which can always takes primitive types as input and return primitive types. Hence autoboxing and autounboxing won’t be required, which improves performance.

Primitive Type Functional Interfaces for Predicate :

The following are various primitive Functional interfaces for Predicate.

  • IntPredicate — always accepts input value of int type
  • LongPredicate — always accepts input value of long type
  • DoublePredicate — always accepts input value of double type

1. IntPredicate

@FunctionalInterface
public interface IntPredicate {
boolean test(int value);
default IntPredicate and(IntPredicate other) { }
default IntPredicate negate() { }
default IntPredicate or(IntPredicate other) { }
}

2. LongPredicate

@FunctionalInterface
public interface LongPredicate {
boolean test(long value);
default LongPredicate and(LongPredicate other) { }
default LongPredicate negate() { }
default LongPredicate or(LongPredicate other) { }
}

3. DoublePredicate

@FunctionalInterface
public interface DoublePredicate {
boolean test(double value);
default DoublePredicate and(DoublePredicate other) { }
default DoublePredicate negate() { }
default DoublePredicate or(DoublePredicate other) { }
}

Demo Program for IntPredicate :

package com.codeFactory.primitiveFunctional;import java.util.function.IntPredicate;public class Test {
public static void main(String... args) {
int x[] = {0, 5, 10, 15, 20};
IntPredicate p = i -> i%2 == 0;
for(int x1 : x) {
if(p.test(x1)) {
System.out.println(x1);
}
}
}
}

Output :

0
10
20

In the above example, autoboxing and autounboxing won’t be performed internally. Hence performance wise improvements are there.

Primitive Type Functional Interfaces for Function :

The following are various primitive Type Functional Interfaces for Function

1. IntFunction : can take int type as input and return any type

@FunctionalInterface
public interface IntFunction<R> {
R apply(int value);
}

2. LongFunction : can take long type as input and return any type

@FunctionalInterface
public interface LongFunction<R> {
R apply(long value);
}

3. DoubleFunction : can take double type as input and return any type

@FunctionalInterface
public interface DoubleFunction<R> {
R apply(double value);
}

4. ToIntFunction : It can take any type as input but always returns int type

@FunctionalInterface
public interface ToIntFunction<T> {
int applyAsInt(T value);
}

5. ToLongFunction : It can take any type as input but always returns long type

@FunctionalInterface
public interface ToLongFunction<T> {
long applyAsLong(T value);
}

6. ToDoubleFunction : It can take any type as input but always returns double type

@FunctionalInterface
public interface ToDoubleFunction<T> {
double applyAsDouble(T value);
}

7. IntToLongFunction : It can take int type as input and returns long type

@FunctionalInterface
public interface IntToLongFunction {
long applyAsLong(int value);
}

8. IntToDoubleFunction : It can take int type as input and returns double type

@FunctionalInterface
public interface IntToDoubleFunction {
double applyAsDouble(int value);
}

9. LongToIntFunction : It can take long type as input and returns int type

@FunctionalInterface
public interface LongToIntFunction {
int applyAsInt(long value);
}

10. LongToDoubleFunction : It can take long type as input and returns double type

@FunctionalInterface
public interface LongToDoubleFunction {
double applyAsDouble(long value);
}

11. DoubleToIntFunction : It can take double type as input and returns int type

@FunctionalInterface
public interface DoubleToIntFunction {
int applyAsInt(double value);
}

12 DoubleToLongFunction : It can take double type as input and returns long type

@FunctionalInterface
public interface DoubleToLongFunction {
long applyAsLong(double value);
}

13. ToIntBiFunction : return type must be int type but inputs can be any type

@FunctionalInterface
public interface ToIntBiFunction<T, U> {
int applyAsInt(T t, U u);
}

14. ToLongBiFunction : return type must be long type but inputs can be any type

@FunctionalInterface
public interface ToLongBiFunction<T,U> {
long applyAsLong(T t, U u);
}

15. ToDoubleBiFunction : return type must be double type but inputs can be any type

@FunctionalInterface
public interface ToDoubleBiFunction<T,U> {
double applyAsDouble(T t, U u);
}

Demo Program to find square of given integer by using Function :

package com.codeFactory.primitiveFunctional;import java.util.function.Function;public class Test {
public static void main(String... args) {
Function<Integer, Integer> f = i -> i * i;
System.out.println(f.apply(5));
}
}

Output :

25

Demo Program to find square of given integer by using IntFunction :

package com.codeFactory.primitiveFunctional;import java.util.function.IntFunction;public class Test {
public static void main(String... args) {
IntFunction<Integer> f = i -> i * i;
System.out.println(f.apply(5));
}
}

Output :

25

Demo Program to find length of the given String by using Function :

package com.codeFactory.primitiveFunctional;import java.util.function.Function;public class Test {
public static void main(String... args) {
Function<String, Integer> f = s -> s.length();
System.out.println(f.apply("Code Factory"));
}
}

Output :

12

Demo Program to find length of the given String by using ToIntFunction :

package com.codeFactory.primitiveFunctional;import java.util.function.ToIntFunction;public class Test {
public static void main(String... args) {
ToIntFunction<String> f = s -> s.length();
System.out.println(f.applyAsInt("Code Factory"));
}
}

Output :

12

Demo Program to find square root of given integer by using Function :

package com.codeFactory.primitiveFunctional;import java.util.function.Function;public class Test {
public static void main(String... args) {
Function<Integer, Double> f = i -> Math.sqrt(i);
System.out.println(f.apply(9));
}
}

Output :

3.0

Demo Program to find square root of given integer by using IntToDoubleFunction :

package com.codeFactory.primitiveFunctional;import java.util.function.IntToDoubleFunction;public class Test {
public static void main(String... args) {
IntToDoubleFunction f = i -> Math.sqrt(i);
System.out.println(f.applyAsDouble(9));
}
}

Output :

3.0

Primitive Version for Consumer :

The following 6 primitive versions available for Consumer :

1. IntConsumer

@FunctionalInterface
public interface IntConsumer {
void accept(int value);
default IntConsumer andThen(IntConsumer after) { }
}

2. LongConsumer

@FunctionalInterface
public interface LongConsumer {
void accept(long value);
default LongConsumer andThen(LongConsumer after) { }
}

3. DoubleConsumer

@FunctionalInterface
public interface DoubleConsumer {
void accept(double value);
default DoubleConsumer andThen(DoubleConsumer after) { }
}

4. ObjIntConsumer

@FunctionalInterface
public interface ObjIntConsumer<T> {
void accept(T t, int value);
}

5. ObjLongConsumer

@FunctionalInterface
public interface ObjLongConsumer<T> {
void accept(T t, long value);
}

6. ObjDoubleConsumer

@FunctionalInterface
public interface ObjDoubleConsumer<T> {
void accept(T t, double value)
}

Demo Program for IntConsumer :

package com.codeFactory.primitiveFunctional;import java.util.function.IntConsumer;public class Test {
public static void main(String... args) {
IntConsumer c = i -> System.out.println("Square : " + i*i);
c.accept(5);
}
}

Output :

Square : 25

Demo Program to increment employee Salary by using ObjDoubleConsumer :

package com.codeFactory.primitiveFunctional;import java.util.ArrayList;
import java.util.function.ObjDoubleConsumer;
class Employee {
String name;
double salary;

public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
@Override
public String toString() {
return "Employee [name=" + name + ", salary=" + salary + "]";
}
}
public class Test {
public static void main(String... args) {
ArrayList<Employee> i = new ArrayList<>();
populate(i);

System.out.println("Before Increment :");
print(i);

ObjDoubleConsumer<Employee> c = (e, d) -> e.salary += d;
for(Employee e : i) {
c.accept(e, 750);
}

System.out.println("After Increment :");
print(i);
}

private static void populate(ArrayList<Employee> i) {
i.add(new Employee("Narendra", 1000));
i.add(new Employee("Amit", 2000));
i.add(new Employee("Vijay", 3000));
i.add(new Employee("Yogi", 4000));
}

private static void print(ArrayList<Employee> i) {
for(Employee e : i) {
System.out.println(e);
}
}
}

Output :

Before Increment :
Employee [name=Narendra, salary=1000.0]
Employee [name=Amit, salary=2000.0]
Employee [name=Vijay, salary=3000.0]
Employee [name=Yogi, salary=4000.0]
After Increment :
Employee [name=Narendra, salary=1750.0]
Employee [name=Amit, salary=2750.0]
Employee [name=Vijay, salary=3750.0]
Employee [name=Yogi, salary=4750.0]

Primitive Versions for Supplier :

The following 4 primitive versions available for Supplier :

1. IntSupplier

@FunctionalInterface
public interface IntSupplier {
int getAsInt();
}

2. LongSupplier

@FunctionalInterface
public interface LongSupplier {
long getAsLong();
}

3. DoubleSupplier

@FunctionalInterface
public interface DoubleSupplier {
double getAsDouble();
}

4. BooleanSupplier

@FunctionalInterface
public interface BooleanSupplier {
boolean getAsBoolean();
}

Demo Program to generate 6 digit random OTP by using IntSupplier :

package com.codeFactory.primitiveFunctional;import java.util.function.IntSupplier;public class Test {
public static void main(String... args) {
IntSupplier s = () -> (int)(Math.random() * 10);

System.out.println("OTP : " + generateOTP(s));
System.out.println("OTP : " + generateOTP(s));
System.out.println("OTP : " + generateOTP(s));
}

private static String generateOTP(IntSupplier s) {
String otp = "";
for(int i=0; i<6; i++) {
otp += s.getAsInt();
}
return otp;
}
}

Output :

OTP : 429493
OTP : 579145
OTP : 888907

--

--