Java Supplier interface example for functional programming
Functional supplier interface in Java tutorial
There are only half a dozen classes you really need to master to become competent in the world of functional programming. The java.util.function package contains well over 40 different components, but if you can garner a good understanding of consumers, predicates, functions, unary types and suppliers, knowledge of the rest of the API simply falls into place. In this functional programming tutorial, we will work through a Java Supplier interface example.
Consumer vs Supplier interfaces
Java’s functional supplier interface can be used any time a function needs to generate a result without any data passed into it. Now, contrast that with Java’s functional Consumer interface which does the opposite. The Consumer interface will pass data, but no result will be returned to the calling program.
Java’s Consumer and Supplier interfaces are functional compliments to one another. If a function needs to both pass data into it and return data as a response, then use the Function interface, because it combines the capabilities of both the Consumer and Supplier interface.
Before we jump into a Java Supplier interface example, it’s a good idea to first reference the JavaDoc in order to see exactly how the API designers describe how the component should be used:
Supplier JavaDoc
java.util.function.Supplier<T>
Type Parameters: T – the type of results supplied by this supplier
@FunctionalInterface
public interface Supplier<T>
This represents a supplier of results. There is no requirement that a new or distinct result be returned when the supplier is invoked.
This functional interface has a single method named get().
As you can see from the JavaDoc, a complete Supplier interface example can be coded simply when you implement the component and override the get() method. The only caveat is that the get() method takes no arguments and returns a valid object as a result. For this Supplier interface tutorial, we will demonstrate how the functional component works by creating a class named RandomDigitSupplier which does exactly what the name implies; it generates a random digit and returns it to the calling program. The range of the randomly generated numbers will be between zero and 10.
Java Supplier interface tutorial
As you can see, the code for the class that implements Java’s Supplier interface is fairly simple. The only requirements are the class declaration and the implementation of the get() method. Within the get() method, the Random class from Java’s util package is used to generate the random digit, but that’s about as complicated as this Java Supplier interface example gets.
package com.mcnz.supplier.example;
import java.util.function.Supplier;
import java.util.*;
/* Java's Functional Supplier interface example */
class RandomDigitSupplier implements Supplier<Integer> {
@Override
public Integer get() {
Integer i = new Random().nextInt(10);
return i;
}
}
To test the Supplier interface, we simply code for a loop which creates a new RandomDigitSupplier interface on each iteration, and prints out the random value.
/* Test class for the Java Supplier interface example */
public class SupplierExampleRunner {
public static void main(String[] args) {
for (int i = 0; i<10; i++) {
RandomDigitSupplier rds = new RandomDigitSupplier();
int randomDigit = rds.get();
System.out.print(randomDigit + " :: " );
}
}
}
A test run of the Supplier interface example generated the following results:
5 :: 4 :: 0 :: 0 :: 9 :: 0 :: 4 :: 2 :: 4 :: 5 ::
Lambda and Supplier interface example
Of course, since Supplier is a functional interface, you can eliminate much of the overhead involved with the creation of a separate class that implements the interface and codes a concrete get() method. Instead, simply provide an implementation through a Lambda expression. This approach allows all of the code above to be condensed into the following:
package com.mcnz.supplier.example; import java.util.function.Supplier; import java.util.*; /* Test class for the Java Supplier interface example */ public class SupplierExampleRunner { public static void main(String[] args) { for (int i = 0; i<10; i++) { //RandomDigitSupplier rds = new RandomDigitSupplier(); Supplier<Integer> rds = () -> new Random().nextInt(10); int randomDigit = rds.get(); System.out.print(randomDigit + " :: " ); } } }
As you can see, the use of a Lambda expression greatly reduces the ceremony required to write functional code.
When to use the Java Supplier interface
Upon first glance, developers without any functional programming experience wonder when a component that seems so simple and straight forward is useful. The first answer to that question lies within Java’s functional package, which defines subtypes such as LongSupplier, IntSupplier, DoubleSupplier and BooleanSupplier.
The second answer is Java’s stream package, which represents the heart and soul of functional programming in Java. For example, the of method of the Collector interface takes a supplier as an argument, similar to the ways of the collect and generate methods of the Stream class. As developers get deeper into the world of functional programming in Java, they discover that the Supplier interfaces, along with various other classes that implement it, are peppered throughout the Java API.
Functional programming in Java is a new concept to those entrenched in traditional, server-side development. But, if developers can familiarize themselves with fundamental components such as the Supplier interface, they can begin to understand more advanced concepts and implement them into their code in a relatively easy fashion.