#
Functions in Java
A Functional Interface
is an interface which contains exactly one abstract method
.
It can have any number of default, static methods, but it can contain ONLY one abstract method.
Lambda expression is used to implement a functional interface abstract method.
Functional Interfaces and lambda expression are introduced in Java 8.
The "functions" are implementations of the Functions<T,R>
functional interfaces.
In my example, I start from a simple Spring Boot application created using Spring initializr.
For my example I create an Employee class first:
package com.exampe.java;
public class Employee {
int id;
String name;
public Employee(int id, String name) {
this.id = id;
this.name = name;
}
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
After that we can create a Function<Employee, String>
implementation:
package com.exampe.java;
import java.util.function.Function;
public class Function1 implements Function<Employee, String> {
@Override
public String apply(Employee employee) {
return employee.getName();
}
}
And below we can see how the functions are used:
package com.exampe.java;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.util.function.Function;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
System.out.println("--------------------------------------------");
// Function using a normal class
Function1 f1 = new Function1();
Employee emp1 = new Employee(11, "Emily");
String str1 = f1.apply(emp1);
System.out.println("Emp name (I) = "+ str1);
// Function using lambda expression
Employee emp2 = new Employee(20, "Dan");
Function<Employee, String> f2 = (emp_2) -> {
return emp_2.getName();
};
String str2 = f2.apply(emp2);
System.out.println("Emp name (II) = "+ str2);
// Function using an inner class
Function<Employee, String> f3 = new Function<Employee, String>() {
public String apply(Employee employee) {
return employee.getName();
}
};
Employee emp3 = new Employee(30, "Helena");
String str3 = f1.apply(emp3);
System.out.println("Emp name (III) = "+ str3);
System.out.println("--------------------------------------------");
System.out.println("End of the execution");
}
}
When we run the application we can see:
--------------------------------------------
Emp name (I) = Emily
Emp name (II) = Dan
Emp name (III) = Helena
--------------------------------------------
End of the execution
Here are some remarks:
- "lambda expressions" could be used always with a functional interface;
- the functions could be implemented by an inner or a normal class.
- a BiFunction is implemented as a Function, but it accepts 2 objects as parameters in the apply() method.
There are a couple of predefined functional interfaces:
Predicate<T>
orBiPredicates<T,U>
: used for filters, we need to define test(T) or test(T, U) method. This method returns a boolean value.Consumer<T>
orBiConsumer<T,U>
: we need to define accept(T) or accept(T, U) method. This method returns no value.Supplier<T>
: we need to return theobject . The get() method will be used to obtain the object returned by the supplier.Function<T, R>
orBiFunction<T,U,R>
: we need to define apply(T) or apply(T, U) method. This method returns an R object.UnaryOperator<T>
orBinaryOperator<T,T>
: we need to return a T object.
Info
T, U, R are generic types of objects.