Chapter 8 - Java for Beginners Course

Built-in Functional Interfaces

When working with lambdas and functional interfaces you’ll find that there are common cases where you’d like to reuse a functional interface definition in several places.

Java provides a set of built-in functional interfaces that is intended to cover some of the common requirements used both in the JDK and that can be used in your code.

The full list can be found in the java.util.function package documentation.

An example of a built-in functional interface

In the example problem that we’ve used over the last sections, we defined a functional interface that we called Filter<E>. In our problem scenario, this interface is responsible of deciding whether an element should be added or not to a result.

public interface Filter<E> {
    boolean filter(E element);
}

If we see this interface in a more general way, this interface receives an element and returns a true/false value, which in functional terms is called a Predicate, that tests if an element complies or not with the definition of our predicate.

You can find the definition of the Predicate<T> interface here, but to simplify, the abstract method it defines is as follows:

public interface Predicate<T> {
	//...

    boolean test(T t);
}

In terms of the requirements we have for our example problem, this is exactly what we want. In that sense, we don’t need to define a Filter<E> interface, we can use the built-in Predicate<T> functional interface that also takes an element and returns a boolean value as a result.

We can then change our code as follows:

In the example code run the JavaListWithLambdaPredicateApp
public class JavaListWithLambdaPredicateApp {

    public static void main(String[] args) {
        // our input list of numbers
        List<Integer> numbers = Arrays.asList(1, 2, 3, 10, 11, 12, 0);

        // call our new `filterNumbers` static method to do the filtering
        List<Integer> filtered = filterNumbers(numbers, element -> element > 5);

        // print out the filtered list
        for (Integer number : filtered) {
            System.out.println(number);
        }
    }

    private static List<Integer> filterNumbers(List<Integer> numbers, Predicate<Integer> filterToUse) {
        List<Integer> filtered = new ArrayList<>();
        // filter the list using the provided `filterToUse`
        for (Integer number : numbers) {
            if (filterToUse.test(number)) {
                filtered.add(number);
            }
        }
        return filtered;
    }
}

Output:

10
11
12