# Functions in Java

In 
Published 2022-12-03

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:

Employee.class
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

There are a couple of predefined functional interfaces:

  • Predicate<T> or BiPredicates<T,U>: used for filters, we need to define test(T) or test(T, U) method. This method returns a boolean value.

  • Consumer<T> or BiConsumer<T,U>: we need to define accept(T) or accept(T, U) method. This method returns no value.

  • Supplier<T> : we need to return the object. The get() method will be used to obtain the object returned by the supplier.

  • Function<T, R> or BiFunction<T,U,R>: we need to define apply(T) or apply(T, U) method. This method returns an R object.

  • UnaryOperator<T> or BinaryOperator<T,T>: we need to return a T object.