In this post we're going to take a look at function composition using two compose functions provided in the Function interface - compose and andThen .

What is function composition?

It all has to do with creating small reusable functions that you can combine to compose new functions.

Now, how can we achieve this using compose and andThen ?

Let's first define two simple functions - times2 and squared .

Function<Integer, Integer> times2 = e -> e * 2; Function<Integer, Integer> squared = e -> e * e;

Next, let's combine them, using compose and andThen .

times2.compose(squared).apply(4); // Returns 32 times2.andThen(squared).apply(4); // Returns 64

As you can see, the difference between compose and andThen is the order they execute the functions. While the compose function executes the caller last and the parameter first, the andThen executes the caller first and the parameter last.

Let's start composing functions

Let's create an example to see how we can use this approach to create small pieces of reusable code - then put them together in different ways.

Consider the following.

We have a list of articles and we need to filter the articles based on different requirements.

Let's start by introducing two basic functions - byAuthor and byTag - that filter articles based on an author and a tag.

BiFunction<String, List<Article>, List<Article>> byAuthor = (name, articles) -> articles.stream() .filter(a -> a.getAuthor().equals(name)) .collect(Collectors.toList()); BiFunction<String, List<Article>, List<Article>> byTag = (tag, articles) -> articles.stream() .filter(a -> a.getTags().contains(tag)) .collect(Collectors.toList());

Both of these functions are BiFunction s - meaning they take two parameters.

byAuthor takes the name of an author and the list of articles, returning a list of the articles written by the author requested.

Same goes for byTag . It takes a tag and the list of articles, returning articles with the requested tag.

Since BiFunction takes two arguments, it only offers the andThen function. You can't put the result of a function into a function that takes two arguments, hence the lack of the compose function.

Moving on - let's also throw in a basic function that sorts a list of articles from newest to oldest and a function that returns the first article a list.

Function<List<Article>, List<Article>> sortByDate = articles -> articles.stream() .sorted((x, y) -> y.published().compareTo(x.published())) .collect(Collectors.toList()); Function<List<Article>, Optional<Article>> first = a -> a.stream().findFirst();

Now that we have our basic functions, let's see how we can use them to compose new functions.

Let's start by composing a function that will return the article that was most recently published.

Function<List<Article>, Optional<Article>> newest = first.compose(sortByDate);

Using the functions first and sortByDate that we created earlier, we're able to create a new function that will return the newest article in a given list.

We can continue to mix these function in several ways to compose functions with new meanings without repeating code.

Finding an author's newest masterpiece.

BiFunction<String, List<Article>, Optional<Article>> newestByAuthor = byAuthor.andThen(newest);

Or just order an author's articles.

BiFunction<String, List<Article>, List<Article>> byAuthorSorted = byAuthor.andThen(sortByDate);

Or maybe you don't care about the author. You just want the newest article based on your favourite tag.

BiFunction<String, List<Article>, Optional<Article>> newestByTag = byTag.andThen(newest);

The point I'm trying to make is that the Function interface and it's compose functions can make it easier and more intriguing to stay DRY by creating small building blocks that can be combined to fit your needs.