Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

Java Dictionary

  1. Home
  2. Java Dictionary
  3. Predicate / Function / Consumer / Supplier

Predicate / Function / Consumer / Supplier

Since: Java 8(2014)

These are the primary functional interfaces added in Java 8. They are used in combination with lambda expressions and method references, each serving one of four roles: testing, transforming, consuming, or supplying values. To summarize: no arguments → Supplier; arguments with a return value → Function; arguments with no return value → Consumer; arguments returning a boolean → Predicate.

Syntax

// Predicate<T>: Takes a T and returns a boolean.
Predicate<T> pred = (T t) -> /* boolean expression */;
boolean result = pred.test(t);

// Function<T, R>: Takes a T and returns an R.
Function<T, R> func = (T t) -> /* value of type R */;
R result = func.apply(t);

// Consumer<T>: Takes a T and returns nothing.
Consumer<T> cons = (T t) -> { /* process */ };
cons.accept(t);

// Supplier<T>: Takes no arguments and returns a T.
Supplier<T> supp = () -> /* value of type T */;
T value = supp.get();

// BiFunction<T, U, R>: Takes two arguments and returns an R.
BiFunction<T, U, R> bif = (T t, U u) -> /* value of type R */;

// UnaryOperator<T>: Takes a T and returns a T of the same type.
UnaryOperator<T> op = (T t) -> /* value of type T */;

Common Functional Interfaces

InterfaceAbstract MethodDescription
Predicate<T>test(T t) → booleanUsed for condition testing. Passed to stream operations like filter().
Function<T, R>apply(T t) → RTransforms a value. Passed to stream operations like map().
Consumer<T>accept(T t) → voidAccepts a value and processes it without returning anything. Passed to operations like forEach().
Supplier<T>get() → TProduces and returns a value with no arguments. Used for lazy evaluation.
BiFunction<T, U, R>apply(T t, U u) → RAccepts two arguments and returns a value.
BiConsumer<T, U>accept(T t, U u) → voidAccepts two arguments and processes them. Passed to operations like Map.forEach().
UnaryOperator<T>apply(T t) → TPerforms a transformation within the same type. A specialization of Function<T,T>.
BinaryOperator<T>apply(T t, T u) → TAccepts two arguments of the same type and returns the same type. Passed to operations like reduce().

Sample Code

FunctionalInterfaces.java
import java.util.*;
import java.util.function.*;

class FunctionalInterfaces {
    public static void main(String[] args) {
        // Predicate: Tests whether a number is even.
        Predicate<Integer> isEven = n -> n % 2 == 0;
        System.out.println(isEven.test(4)); // Prints "true".
        System.out.println(isEven.test(7)); // Prints "false".

        // Composing Predicates: Combine with and() / or() / negate().
        Predicate<Integer> isPositive = n -> n > 0;
        Predicate<Integer> isEvenAndPositive = isEven.and(isPositive);
        System.out.println(isEvenAndPositive.test(4)); // Prints "true".
        System.out.println(isEvenAndPositive.test(-2)); // Prints "false".

        // Function: Converts a string to uppercase.
        Function<String, String> toUpper = String::toUpperCase;
        System.out.println(toUpper.apply("hello")); // Prints "HELLO".

        // Composing Functions: Chain with andThen().
        Function<String, Integer> toLength = String::length;
        Function<String, Integer> upperLength = toUpper.andThen(toLength);
        System.out.println(upperLength.apply("hello")); // Prints "5".

        // Consumer: Prints each element in a list.
        Consumer<String> printer = s -> System.out.println("> " + s);
        List.of("A", "B", "C").forEach(printer);

        // Supplier: Lazily creates a default value.
        Supplier<List<String>> listFactory = ArrayList::new;
        List<String> newList = listFactory.get();
        newList.add("item");
        System.out.println(newList); // Prints "[item]".
    }
}

The command looks like this:

javac FunctionalInterfaces.java
java FunctionalInterfaces
true
false
true
false
HELLO
5
> A
> B
> C
[item]

Common Mistakes

Common Mistake 1: Throwing a checked exception inside a lambda and getting a compile error

Standard functional interfaces such as Runnable and Consumer do not declare checked exceptions. Throwing IOException or similar inside a lambda assigned to these types causes a compile error.

FunctionalInterfacesNg1.java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.function.Consumer;

class FunctionalInterfacesNg1 {
    public static void main(String[] args) {
        Consumer<String> writer = filename -> {
            Files.writeString(Path.of(filename), "Gojo Satoru's technique notes");
        };
        writer.accept("memo.txt");
    }
}

The command looks like this:

javac FunctionalInterfacesNg1.java
java FunctionalInterfacesNg1
FunctionalInterfacesNg1.java:9: error: unreported exception IOException; must be caught or declared to be thrown
            Files.writeString(Path.of(filename), "Gojo Satoru's technique notes");
                             ^

Wrap the checked exception in a try-catch inside the lambda, or define a custom functional interface that declares the checked exception.

FunctionalInterfacesOk1.java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.function.Consumer;

class FunctionalInterfacesOk1 {
    public static void main(String[] args) {
        Consumer<String> writer = filename -> {
            try {
                Files.writeString(Path.of(filename), "Gojo Satoru's technique notes");
                System.out.println("Write completed: " + filename);
            } catch (IOException e) {
                System.err.println("Write error: " + e.getMessage());
            }
        };
        writer.accept("memo.txt");
    }
}

The command looks like this:

javac FunctionalInterfacesOk1.java
java FunctionalInterfacesOk1
Write completed: memo.txt

Common Mistake 2: Confusing Consumer<T> with Function<T,R> and getting a compile error

Consumer<T> has no return value (void). Assigning a lambda that returns a value to a Consumer<T> variable causes a compile error. Use Function<T,R> when you need a return value.

FunctionalInterfacesNg2.java
import java.util.function.Consumer;

class FunctionalInterfacesNg2 {
    public static void main(String[] args) {
        Consumer<String> getName = name -> "Sorcerer: " + name;
        System.out.println(getName.accept("Itadori Yuji"));
    }
}

The command looks like this:

javac FunctionalInterfacesNg2.java
java FunctionalInterfacesNg2
FunctionalInterfacesNg2.java:5: error: incompatible types: bad return type in lambda expression
        Consumer<String> getName = name -> "Sorcerer: " + name;
                                                        ^

Use Function<T,R> when the lambda returns a value. Consumer<T>'s accept() returns void, so lambdas that produce a result cannot be used with it.

FunctionalInterfacesOk2.java
import java.util.function.Function;
import java.util.function.Consumer;

class FunctionalInterfacesOk2 {
    public static void main(String[] args) {
        Function<String, String> getName = name -> "Sorcerer: " + name;
        System.out.println(getName.apply("Itadori Yuji"));

        Consumer<String> printer = name -> System.out.println("Sorcerer: " + name);
        printer.accept("Kugisaki Nobara");
    }
}

The command looks like this:

javac FunctionalInterfacesOk2.java
java FunctionalInterfacesOk2
Sorcerer: Itadori Yuji
Sorcerer: Kugisaki Nobara

Notes

These interfaces are part of the java.util.function package and are used as the target types for lambda expressions and method references. They are also widely used in the Stream API and Optional, so learning them will be very useful.

Predicate supports composition via and() / or() / negate(), and Function supports composition via andThen() / compose(). Using primitive-specialized variants such as IntPredicate, IntFunction<R>, IntConsumer, and IntSupplier avoids the cost of autoboxing.

For how to write lambda expressions, see 'Lambda Expressions / (x) -> x * 2'.

If you find any errors or copyright issues, please .