Skip to content

A Detailed Guide On Java Built-In Functional Interfaces

This lesson details about the various functional interfaces that fall under major 4 categories.

Gopi Gorantala
Gopi Gorantala
4 min read

Table of Contents

Introduction

Java provides a lot of predefined functional interfaces for us to use.

The new Function API introduced in Java SE 8 defines several built-in functional interfaces, providing target types for lambda expressions and method references.

So if we break down all the interfaces we were given in the functions package, they are packed into 4 types, and all of them are either of the four interfaces we are discussing.

  1. Consumer
  2. Supplier
  3. Function
  4. Predicate

Sketch

Types of Functional Interfaces

As per the sketch above, let us talk in detail about these functional interfaces.

1. Consumer interface

The Consumer interface in Java is a functional interface that takes a single argument of a specified type and returns no result. Its functional method is called accept(). Here is the syntax for the Consumer interface:

@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
}

In this example, T a type parameter represents the type of argument that the Consumer will accept. The @FunctionalInterface annotation is optional but often indicates that the interface is intended to be a functional interface.

To use the Consumer interface, you can create an instance of it and pass it as an argument to a method that expects a Consumer.

An example is shown below:

List<String> names = Arrays.asList("John", "Jane", "Bob");

Consumer<String> printName = name -> System.out.println(name);

names.forEach(printName);

In this example, a Consumer instance called printName is created using a lambda expression that takes a String argument and prints it to the console. The forEach() method of the List class is called with printName as an argument, causing it to be executed for each element in the list. As a result, the names "John", "Jane", and "Bob" are printed to the console.

The Consumer interface is commonly used in scenarios where you must act on each collection element, such as printing, logging, or processing the elements.

2. Supplier Interface

The Supplier interface in Java is a functional interface that takes no arguments and returns a specified type value. Its functional method is called get(). This is opposite to Consumer Interface.

Here is the syntax for the Supplier interface:

@FunctionalInterface
public interface Supplier<T> {
    T get();
}

In this example, T is a type parameter that represents the type of value that the Supplier will return. The @FunctionalInterface annotation is optional but is often used to indicate that the interface is intended to be a functional interface.

To use the Supplier interface, you can create an instance of it and call its get() method to obtain a value. Here is an example:

Supplier<Integer> randomNumberSupplier = () -> (int) (Math.random() * 100);

int randomNumber = randomNumberSupplier.get();

System.out.println("Random number: " + randomNumber);

In this example, a Supplier instance called randomNumberSupplier is created using a lambda expression that generates a random integer between 0 and 100. The get() method of Supplier is then called to obtain a random number printed to the console.

The Supplier interface is commonly used when generating or supplying values on demand, such as when initializing objects or populating collections.

3. Function Interface

The Function interface in Java is a functional interface that takes a single argument of a specified type and returns a value of a different type. Its functional method is called apply().

Here is an example of using the Function interface:

Function<String, Integer> stringLength = str -> str.length();

int length = stringLength.apply("hello");

System.out.println("Length of string: " + length);

In this example, a Function instance called stringLength is created using a lambda expression that takes a String argument and returns its length as an Integer. The apply() method of the Function is then called with the string "hello" as an argument, which returns the length of the string (which is 5). The length is then printed to the console.

The Function interface is commonly used in scenarios where you need to transform or convert values, such as when processing data or performing calculations. Another example of using the Function interface is to convert a string to an integer, like this:

Function<String, Integer> stringToInt = str -> Integer.parseInt(str);

int num = stringToInt.apply("42");

System.out.println("Number: " + num);

In this example, a Function instance called stringToInt is created using a lambda expression that takes a String argument and converts it to an Integer. The apply() method of the Function is then called with the string "42" as an argument, which returns the integer value 42. The integer is then printed to the console.

4. Predicate Interface

The Predicate interface in Java is a functional interface that takes a single argument of a specified type and returns a boolean value. Its functional method is called test(). Here is an example of using the Predicate interface:

Predicate takes an object/variable and checks to see if that satisfies some criteria. Most of the time we use this in filtering data.
Predicate<Integer> isEven = num -> num % 2 == 0;

boolean result1 = isEven.test(4); // returns true
boolean result2 = isEven.test(7); // returns false

System.out.println("Result1: " + result1);
System.out.println("Result2: " + result2);

In this example, a Predicate instance called isEven is created using a lambda expression that takes an Integer argument and checks whether it is even (by checking whether the remainder after division by 2 is 0). The test() method of the Predicate is then called with the integers 4 and 7 as arguments, which return true and false respectively. The results are then printed to the console.

The Predicate interface is commonly used in scenarios where you must test or filter values based on some condition, such as when searching or sorting data. Another example of using the Predicate interface is to check if a string is longer than a certain length, like this:

Predicate<String> isLongerThan5 = str -> str.length() > 5;

boolean result3 = isLongerThan5.test("hello"); // returns false
boolean result4 = isLongerThan5.test("goodbye"); // returns true

System.out.println("Result3: " + result3);
System.out.println("Result4: " + result4);

In this example, a Predicate instance called isLongerThan5 is created using a lambda expression that takes a String argument and checks whether its length is greater than 5. The test() method of the Predicate is then called with the strings "hello" and "goodbye" as arguments, which return false and true respectively. The results are then printed to the console.

Next Up?

You will learn each in detail in the next lessons with examples and explanations.

Java Streams APIJava

Gopi Gorantala Twitter

Gopi is an engineering leader with 12+ of experience in full-stack development—a specialist in Java technology stack. He worked for multiple startups, the European govt, and FAANG in India and Europe.

Comments


Related Posts

Members Public

Differences Between JDK, JRE, and JVM?

Short answer JDK, JRE, and JVM are essential components of the Java platform, each serving a distinct purpose. Here are the key differences between them: 1. JDK (Java Development Kit): The JDK is used by developers to write, compile, and debug Java code. 2. JRE (Java Runtime Environment): End-users use

Members Public

Difference Between String and char[] in Java

Short answer Strings String is an object with many helpful methods. String class in Java's standard library is designed to handle text as a sequence of characters. A string of characters (string object) is non-modifiable or immutable in Java. Once you've created it, you cannot modify

Members Public

What is an Object class in Java?

Short answer Object class is the super class of every class you can create. In Java, a class extends another class using the keyword extends. If you don't have any other class to extend, that's fine. The compiler will make your class extend the Object class.