Java Supplier tutorial shows how to work with the Supplier functional interface in Java. Supplier represents an operation that returns a result.
last modified March 5, 2024
In this article we show how to work with the Supplier functional interface in Java.
Java Supplier is a functional interface which represents an operation that returns a result. Supplier does not take any arguments.
A Supplier<T> is designed to produce a value without taking any explicit input parameters. It does this by calling a method or generating a value internally.
@FunctionalInterface public interface Supplier<T> {
T get();
}
T is the type of results supplied by the supplier.
Supplier offers a concise and convenient way to represent value-providing functions, promoting lazy evaluation, code clarity, and compatibility with functional programming concepts in Java.
The following example creates a simple supplier.
Main.java
void main() {
var words = List.of("falcon", "cup", "fun", "cloud");
var res = upperWords(words);
System.out.println(res);
}
List<String> upperWords(List<String> words) {
var uppered = new ArrayList<String>();
for (var word : words) {
Supplier<String> upperSupplier = word::toUpperCase;
uppered.add(upperSupplier.get());
}
return uppered;
}
The program turns words into uppercase using upperSupplier.
Supplier<String> upperSupplier = word::toUpperCase;
The Supplier returns a string. It references the toUpperCase method of the String type. It may look like the supplier is taking an argument, but it is not; it is taking a reference to a method which itself takes the argument.
The expression word::toUpperCase refers to the bound method reference for the toUpperCase method on the specific word instance. Since word is a variable in the loop, a new Supplier<String> is created for each word individually. The Supplier<String> method on the Supplier simply invokes toUpperCase on that specific captured instance.
$ java Main.java [FALCON, CUP, FUN, CLOUD]
The next example creates a function that returns products.
Main.java
Supplier<List<Product>> productSupplier = () -> {
return List.of(
new Product(1, "Product A"),
new Product(2, "Product B"),
new Product(3, "Product C"),
new Product(4, "Product D"),
new Product(5, "Product E"));
};
void main() {
productSupplier.get().stream().limit(3).forEach(System.out::println);
}
record Product(int id, String name) { }
The defined supplier returns a list of products.
productSupplier.get().stream().limit(3).forEach(System.out::println);
We retrieve the list with get. We transform it into a stream and fetch the first three products from the list.
$ java Main.java Product[id=1, name=Product A] Product[id=2, name=Product B] Product[id=3, name=Product C]
IntSupplier represents a supplier of int-valued results. This is the int-producing primitive specialization of Supplier.
Main.java
void main() {
IntSupplier randIntSupp = () -> new Random().nextInt(40);
System.out.println(randIntSupp.getAsInt());
System.out.println(randIntSupp.getAsInt());
System.out.println("--------------------");
IntStream.generate(randIntSupp).limit(6).forEach(System.out::println);
}
The program creates a supplier of random integers.
IntSupplier randIntSupp = () -> new Random().nextInt(40);
The IntSupplier returns a random integer in range [0,40).
System.out.println(randIntSupp.getAsInt());
We get a random integer with getAsInt.
IntStream.generate(randIntSupp).limit(6).forEach(System.out::println);
A stream of six random integers is generated.
31 4 10 30 15 8
The next example creates a supplier which generates a sequence of fibonacci values.
Main.java
Supplier<Long> fibonacciSupplier = new Supplier<Long>() {
long a = 0, b = 1;
public Long get() {
long nextValue = a + b;
a = b;
b = nextValue;
return a;
}
};
void main() {
Stream<Long> fibs = Stream.generate(fibonacciSupplier);
fibs.limit(20).forEach(e -> System.out.print(STR."\{e} "));
}
We create a stream from the fibonacci supplier and fetch first twenty values.
$ java Main.java 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765
The Supplier interface is used in various Java APIs. For instance, the CompletableFuture.supplyAsync returns a CompletableFuture that is asynchronously completed.
Main.java
void main() throws ExecutionException, InterruptedException {
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
return new Random().nextInt(40);
});
System.out.println(future.get());
}
The program returns a random integer in range [0,40) in an async operation.
In this article we have worked with Java Supplier interface.
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { throw new IllegalStateException(e); } return new Random().nextInt(40); });
CompletableFuture takes a Supplier as a parameter.
Java Supplier - language reference
In this article we have worked with the Supplier Java interface.
My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.
List all Java tutorials.