## Overview

The Function interface in Java is primarily used for its *map* operation on a Java stream. In the last post, we saw about predicate chaining in Java. In this post, we will learn about Function chaining in Java.

## Function interface in Java

A Function is a functional interface (has a single abstract method called **accept**) that accepts one argument and produces a result.

**Example:** We can create a stream of integers, map each integer element to double (2x) of its value, and collect the result as a list.

```
List<Integer> integers = List.of(1, 2, 3, 4, 5);
Function<Integer, Integer> doubleFunction = i -> i * 2;
System.out.println(integers.stream()
.map(doubleFunction)
.collect(Collectors.toList())); //[2, 4, 6, 8, 10]
```

Note: We could have used the function inline in the *map* call without declaring it separately.

```
System.out.println(integers.stream()
.map(i -> i * 2)
.collect(Collectors.toList())); //[2, 4, 6, 8, 10]
```

To square each element, we can define a different function and use it.

```
Function<Integer, Integer> square = i -> i * i;
System.out.println(integers.stream()
.map(square)
.collect(Collectors.toList())); //[1, 4, 9, 16, 25]
```

## Applying multiple functions

What if we want to apply both *square* and *double* functions to an element one after another?

Easier/Obvious options - We could either

- Create a new function to do it.
- Use the previously created functions (
*doubleFunction*and*square*) by chaining two*Function#map*calls

### Creating a new function to square and double

We can create a new function (lambda expression) which maps an element by first *squaring* it and then *doubling* the previous result.

```
System.out.println(integers.stream()
.map(i -> (i * i) * 2)
.collect(Collectors.toList())); //[2, 8, 18, 32, 50]
```

### Multiple map calls (Chaining map calls)

We could apply the map multiple times (chaining) as shown below. The first map *squares* the integer and the second map *doubles* the result of the previous map result.

```
Function<Integer, Integer> doubleFunction = i -> i * 2;
Function<Integer, Integer> square = i -> i * i;
System.out.println(integers.stream()
.map(square)
.map(doubleFunction)
.collect(Collectors.toList())); //[2, 8, 18, 32, 50]
```

Can we do better (a more idiomatic approach)?

Yes!!. The Function interface has two default methods named **andThen()** and **compose()** which allow us to compose methods.

## Function andThen - To chain a function at the end

**Method Signature:**

```
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after)
```

The **andThen()** method accepts a function as an argument and returns a **composed function**. The composed function first applies *this* function (the function instance on which *andThen* was called) to the input and then applies the *after* function to the result.

### Function#andThen example

Let us compose a function using the *square* and the *double* functions we have to build a function instance which first *squares* an integer and then *doubles* it.

```
Function<Integer, Integer> squareAndDouble = square.andThen(doubleFunction);
System.out.println(integers.stream()
.map(squareAndDouble)
.collect(Collectors.toList())); // [2, 8, 18, 32, 50]
```

`square.andThen(doubleFunction)`

returns a new function which first applies the *square* function to the input and then applies *double* function to the previous output.

Similarly, we can compose the *double* function and the *square* function as (first double and then square),

```
Function<Integer, Integer> doubleAndSquare = doubleFunction.andThen(square);
System.out.println(integers.stream()
.map(doubleAndSquare)
.collect(Collectors.toList())); //[4, 16, 36, 64, 100]
```

## Function compose - To chain a function at the beginning

**Method signature:**

```
default <V> Function<V, R> compose(Function<? super V, ? extends T> before)
```

The **compose()** method accepts a function as an argument and returns a **composed function**. The composed function first applies the *before* function to the input, and then applies *this* function (the function instance on which *compose* was called) to the result.

### Function#compose example

To apply *square* function followed by *double* function, we use the **compose()** method as shown below.

```
Function<Integer, Integer> squareAndDouble = doubleFunction.compose(squareFunction);
System.out.println(integers.stream()
.map(squareAndDouble)
.collect(Collectors.toList())); //[2, 8, 18, 32, 50]
```

To apply it in the reverse order,

```
Function<Integer, Integer> doubleAndSquare = squareFunction.compose(doubleFunction);
System.out.println(integers.stream()
.map(doubleAndSquare)
.collect(Collectors.toList())); //[4, 16, 36, 64, 100]
```

From this we can infer that *A.andThen(B)* is the same as *B.compose(A)*.

## Chaining to a BiFunction

A BiFunction is a function, but it accepts two arguments and returns a result.

Example: We create a multiplication function which takes in two integers and returns the product of them.

```
BiFunction<Integer, Integer, Integer> multiply = (a, b) -> a * b;
System.out.println(multiply.apply(2, 3)); //6
```

The **BiFunction** also has an **andThen()** method with the below signature

```
default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after)
```

It returns a composed function which applies *this* function first to the input. And then it applies the passed function (*after*) to the result. Note that it accepts a * Function* and still returns a

*. Let us look at an example.*

**BiFunction**### Example of BiFunction composition

With the *multiply* BiFunction we have, let us use the *square* function, i.e., we will take in two integers, multiply them and square the result.

```
Function<Integer, Integer> square = i -> i * i;
BiFunction<Integer, Integer, Integer> multiply = (a, b) -> a * b;
BiFunction<Integer, Integer, Integer> multiplyAndSquare = multiply.andThen(square);
System.out.println(multiplyAndSquare.apply(2, 3)); //36
```

It allows only *Functions* to be chained. This is because the result of applying a BiFunction will result in a single value. We cannot chain another BiFunction to it, as a BiFunction requires two arguments.

For the same reason, a BiFunction does not have a **compose** method. The result of the *before* function passed as the argument would result in a single-valued output. We cannot invoke the (*after*) BiFunction with that.

### Creating a transformation chain

Let me finish this post by showing how we can create a series of transformation which involves changing the type of the value (result). Let us convert the previous result (of multiplying and squaring) to a string.

```
BiFunction<Integer, Integer, String> multiplyAndSquareWithResultAsString = multiplyAndSquare
.andThen(String::valueOf);
String result = multiplyAndSquareWithResultAsString.apply(2, 3);
System.out.println(result); //36
```

`String::valueOf`

is a method reference of the lambda expression `result -> String.valueOf(result)`

.

The created composed function mapping chain is,

```
multiply.andThen(square)
.andThen(String::valueOf);
```

## Conclusion

In this post we learned how we can do function chaining in Java 8. We learnt about the *andThen* and the *compose* methods in the Function interface. Finally, we also looked at the *andThen* method of BiFunction interface too.

To learn more about Java streams and other Java features, take a look at other java-stream and java-8 posts.