Java 8 features — Function (Functional Interfaces)

Uttam Pasare
Javarevisited
Published in
3 min readOct 22, 2023

Hello techies, writing this article for beginners to understand the concept of functional interfaces and described how we can make a use of Function,

Java 8 has introduced several functional interfaces and Function is one of them. This is function which accepts one argument and produces a output. Since this is functional interface, it can be used as assignment for lambda expression and method reference.

Functional interface means the interface which has only single abstract method, due to which it is also called as SAM (Single Abstract Method) interface. These interfaces by rule must have only one abstract method but can have one or more static and default methods.

@FunctionalInterface
public interface Function<T,R>
Type Parameters:
T - the type of the input to the function
R - the type of the result of the function

apply(T t) Applies this function to the given argument.

In following example Function takes String as an input and returns capitalized String as an output. We can call apply method of a function with arguments e.g. capitalizeFunction.apply(name). If you look closely same function can be defined in two different ways,

  1. accept input and apply uppercase logic on input argument
  2. giving method reference of toUpperCase method of String class

both returns the same result

Function<String,String> capitalizeFunction = name -> name.toUpperCase();
Function<String,String> capitalizeFunction = String::toUpperCase; -- Method reference
List<Employee> employees = new ArrayList<>();
employees.add(new Employee().setName("John").setId(100).setGender("Male").setSalary(25000.00));
employees.add(new Employee().setName("Alex").setId(101).setGender("Male").setSalary(24000.00));
employees.add(new Employee().setName("Merry").setId(102).setGender("Female").setSalary(23000.00));
employees.add(new Employee().setName("Sam").setId(103).setGender("Male").setSalary(26000.00));
employees.add(new Employee().setName("Angela").setId(104).setGender("Female").setSalary(27000.00));

Function<String,String> capitalizeFunction = String::toUpperCase;
employees.stream()
.map(Employee::getName)
.forEach(name -> System.out.println(capitalizeFunction.apply(name)));

Output
JOHN
ALEX
MERRY
SAM
ANGELA

andThen(Function<? super R,? extends V> after)
Returns a composed function that first applies this function to its input, and then applies the after function to the result.

Following example allows to chain functions together, as shown below we are capitalizing the given argument and then doing substring on it e.g. capitalizeFunction.andThen(substringFunction).apply(name).

Function<String,String> capitalizeFunction = String::toUpperCase;
Function<String,String> substringFunction = name -> name.substring(2);

employees.stream().map(Employee::getName)
.forEach(name -> System.out.println(capitalizeFunction.andThen(substringFunction).apply(name)));

Output
HN
EX
RRY
M
GELA

compose(Function<? super V,? extends T> before)
Returns a composed function that first applies the before function to its input, and then applies this function to the result.

Compose method allows us to combine multiple functions together and execute them sequentially, in below example composedResult is a target function which is combining capitalize and substring function

Function<String,String> capitalizeFunction = String::toUpperCase;
Function<String,String> substringFunction = name -> name.substring(2);

Function<String,String> composedResult = substringFunction.compose(capitalizeFunction);
employees.forEach(employee -> System.out.println(composedResult.apply(employee.getName())));

Output
HN
EX
RRY
M
GELA

BiFunction<T,U,R> — this function accepts two arguments as input and returns the result

In certain cases, we need to use multiple arguments to the function to get desired output, in such cases we can use BiFunction.

@FunctionalInterface
public interface BiFunction<T,​U,​R>

T - the type of the first argument to the function
U - the type of the second argument to the function
R - the type of the result of the function

Following example, name and gender are two arguments to the function which returns formatted name as a result.

BiFunction<String, String, String> concat = 
(name,gender) -> String.format("%s %s", name,gender);
employees.forEach(employee ->
System.out.println(concat.apply(employee.getName(), employee.getGender()))
);

Output
John Male
Alex Male
Merry Female
Sam Male
Angela Female

Thank you for going through the article, above example can be downloaded from Git — https://github.com/uttam-pasare/Java8-Features.git

LinkedIn — www.linkedin.com/in/uttam-pasare

--

--

Uttam Pasare
Javarevisited

Hello, This is Uttam Pasare working as a Java Professional, love to explore, learn & share knowledge around software technologies.