Study guide

7.1 Built-in Functional Interfaces in java.util.function

Oracle Java SE 21 Developer 1Z0-830

Track your progress as you read

Finished sections get a check mark.

1 Chapter 1: Java Basics, Primitive Types, and Operators

1.1 Program Structure, Primitives, Literals, Scopes, and var 1.2 Operators, Precedence, and Type Casting 1.3 Strings, Text Blocks, and StringBuilder 1.4 Date and Time APIs (java.time)

2 Chapter 2: Controlling Program Flow & Pattern Matching

2.1 Conditional Logic: if-else and Ternary Operators 2.2 Switch Statements and Switch Expressions 2.3 Pattern Matching for switch and instanceof 2.4 Loops and Branching Statements

3 Chapter 3: Object-Oriented Design & Class Architecture

3.1 Class Declarations, Constructors, and Object Lifecycle 3.2 Encapsulation and Access Modifiers 3.3 Inheritance, Method Overriding, and Polymorphism 3.4 Abstract Classes and Interfaces 3.5 Nested, Inner, Local, and Anonymous Classes 3.6 Method Overloading, Overload Resolution, and Varargs

4 Chapter 4: Modern Java Data Modeling: Records, Enums, and Sealed Types

4.1 Java Records, Canonical/Compact Constructors, and Component Accessors 4.2 Java Enums: Fields, Methods, and Abstract Constant-Specific Behavior 4.3 Sealed Classes and Interfaces: permits, final, non-sealed, and Hierarchy Architecture 4.4 Advanced Record Patterns (JEP 440), Nested Deconstruction, and Sealed Hierarchy Exhaustiveness

5 Chapter 5: Exception Handling and Annotations

5.1 Exception Hierarchy: Checked vs. Unchecked Exceptions 5.2 Exception Handling: try, catch, finally, and Multi-Catch 5.3 Resource Management: try-with-resources and AutoCloseable 5.4 Custom Exceptions and Best Practices 5.5 Java Annotations: Built-in, Meta-Annotations, and Custom Types

6 Chapter 6: Generics and the Collections Framework

6.1 Generics Fundamentals and Generic Methods 6.2 Wildcards, Type Bounds, and Type Erasure 6.3 Core Collections: Lists, Sets, Queues, and Maps 6.4 Sequenced Collections in Java 21 6.5 Sorting, Comparable, and Comparator 6.6 Arrays: Creation, Multidimensional Forms, and the Arrays Utility Class

7 Chapter 7: Functional Programming & Lambda Expressions

7.1 Built-in Functional Interfaces in java.util.function 7.2 Lambda Expressions, Variable Scopes, and Effectively Final 7.3 Method References: Four Varieties and Edge Cases 7.4 Working with java.util.Optional

8 Chapter 8: The Stream API and Data Pipelines

8.1 Stream Creation and Intermediate Operations 8.2 Terminal Operations and Reductions 8.3 Advanced Collectors, Grouping, Partitioning, and Teeing 8.4 Primitive Streams and Parallel Stream Processing

9 Chapter 9: Concurrency, Multithreading, and Virtual Threads

9.1 Thread Fundamentals, Creation, and Lifecycle 9.2 Thread Safety, Synchronization, and the Java Memory Model 9.3 Concurrency Utilities: ExecutorService, Callable, and Future 9.4 Concurrent Collections, Atomics, and Explicit Locks 9.5 Virtual Threads in Java 21 (Carrier Threads, Pinning, and Best Practices)

10 Chapter 10: The Java Platform Module System (JPMS)

10.1 Module Architecture and module-info.java Declarations 10.2 Module Directives: requires, exports, opens, provides, and uses 10.3 Modular Compilation, Packaging, and CLI Execution 10.4 Module Types, Migration Strategies, ServiceLoader SPI, and JLink

11 Chapter 11: Java I/O, NIO.2, and Object Serialization

11.1 Classic Java I/O Streams and Readers/Writers 11.2 Java NIO.2 File API: Path, Paths, and File System Operations 11.3 Advanced NIO.2 Stream Operations and Directory Traversal 11.4 Java Object Serialization and Record Serialization

12 Chapter 12: Implementing Localization and Internationalization

12.1 Locales and Resource Bundles 12.2 Formatting and Parsing Numbers, Currencies, Dates, Times, and Messages

7.1 Built-in Functional Interfaces in java.util.function

Key Takeaways Explain This Topic AI

A functional interface defines exactly one abstract method (Single Abstract Method or SAM contract), while permitting any number of default, static, and Object-inherited public methods.

The four foundational functional interface families are Supplier<T> (T get()), Consumer<T> (void accept(T)), Predicate<T> (boolean test(T)), and Function<T, R> (R apply(T)).

Bi-variants accept two arguments: BiConsumer<T, U>, BiPredicate<T, U>, and BiFunction<T, U, R>; there is no BiSupplier because methods in Java cannot return two distinct values.

Primitive specializations (such as IntPredicate, ToLongFunction<T>, DoubleSupplier, and IntToDoubleFunction) optimize performance by eliminating autoboxing and unboxing overhead.

Last updated: September 2026

Built-in Functional Interfaces in java.util.function

Functional programming in Java revolves around functional interfaces —interfaces that declare exactly one abstract method. Introduced in Java 8 and continuously leveraged across modern Java standard APIs, functional interfaces act as target types for lambda expressions and method references. For the Oracle Certified Professional: Java SE 21 Developer (1Z0-830) exam, you must demonstrate comprehensive mastery of the java.util.function package, including core families, binary variants, primitive specializations, operator sub-interfaces, and composition combinators.

1. Functional Interfaces & The SAM Contract

A functional interface is defined by its Single Abstract Method (SAM) contract. An interface is a valid functional interface if and only if it contains exactly one abstract method.

The @FunctionalInterface Annotation

The @FunctionalInterface annotation is optional, but it instructs the Java compiler to verify that the annotated interface strictly adheres to the SAM contract. If an annotated interface declares zero abstract methods or more than one abstract method, the compiler generates an error. @FunctionalInterface

  • public interface StringTransformer {
  • String transform(String input); // Single Abstract Method (SAM)
  • // Default methods do NOT count toward SAM count
  • default String transformTwice(String input) {
  • return transform(transform(input));
  • }
  • // Static methods do NOT count toward SAM count
  • static StringTransformer identity() {
  • return s -> s;
  • }
  • // Public methods matching java.lang.Object signatures do NOT count toward SAM count
  • @Override
  • boolean equals(Object obj);
  • @Override
  • String toString();
  • }

Important

Methods Matching java.lang.Object : Any public method declared in an interface that overrides a public method of java.lang.Object (such as boolean equals(Object) , int hashCode() , or String toString() ) does not count toward the interface's abstract method count. This is because every implementing class automatically inherits an implementation from java.lang.Object .

2. The Four Core Functional Interface Families

All 43 functional interfaces in java.util.function derive from or specialize four foundational interface archetypes: +-------------------------------------------------------------------------------+

  • | THE FOUR CORE FUNCTIONAL FAMILIES |
  • | |
  • | 1. Supplier<T> : () -> T [Produces data, takes nothing] |
  • | 2. Consumer<T> : (T) -> void [Consumes data, returns nothing] |
  • | 3. Predicate<T> : (T) -> boolean [Evaluates boolean condition] |
  • | 4. Function<T, R> : (T) -> R [Transforms input T to output R] |
  • +-------------------------------------------------------------------------------+
  • 1. Supplier<T>
  • SAM : T get()

Purpose : Generates or supplies an instance of type T without requiring any input parameters.

Common Use : Lazy evaluation, factory methods, default value generation. Supplier<LocalDate> todaySupplier = () -> LocalDate.now();

  • Supplier<List<String>> listFactory = ArrayList::new;
  • LocalDate now = todaySupplier.get();
  • 2. Consumer<T>
  • SAM : void accept(T t)

Purpose : Accepts a single input argument of type T and performs a side-effect operation, returning no result ( void ).

Default Method : default Consumer<T> andThen(Consumer<? super T> after) executes the current consumer followed by the after consumer. Consumer<String> printer = s -> System.out.print("[" + s + "]");

  • Consumer<String> logger = s -> System.out.println(" Logged: " + s.length());
  • Consumer<String> pipeline = printer.andThen(logger);
  • pipeline.accept("Java 21"); // Prints: [Java 21] Logged: 7
  • 3. Predicate<T>
  • SAM : boolean test(T t)

Purpose : Evaluates a condition against an argument of type T , returning a primitive boolean .

Default Methods :

  • default Predicate<T> and(Predicate<? super T> other) (Logical AND with short-circuit evaluation)
  • default Predicate<T> or(Predicate<? super T> other) (Logical OR with short-circuit evaluation)
  • default Predicate<T> negate() (Logical NOT)

Static Factory Methods :

static <T> Predicate<T> isEqual(Object targetRef) (Uses Objects.equals )

static <T> Predicate<T> not(Predicate<? super T> target) (Java 11+ helper for method references) Predicate<String> isNonEmpty = s -> s != null && !s.isBlank();

  • Predicate<String> isShort = s -> s.length() < 10;
  • Predicate<String> validShortName = isNonEmpty.and(isShort);
  • // Java 11+ Predicate.not with method references
  • List<String> items = List.of("A", "", "B", " ");
  • long count = items.stream().filter(Predicate.not(String::isBlank)).count(); // 2
  • 4. Function<T, R>
  • SAM : R apply(T t)

Purpose : Accepts an argument of type T and computes a result of type R .

Default Methods :

default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) : Evaluates this first, then passes the result to after .

default <V> Function<V, R> compose(Function<? super V, ? extends T> before) : Evaluates before first, then passes the result to this .

Static Method : static <T> Function<T, T> identity() returns a function that always returns its input argument. Function<String, Integer> parse = Integer::parseInt;

Function<Integer, Integer> square = x -> x * x;

  • // andThen: parse first, then square: parse(s) -> square(result)
  • Function<String, Integer> parseAndSquare = parse.andThen(square);
  • int res1 = parseAndSquare.apply("5"); // 25
  • // compose: square first, then parse: square(x) -> parse(result) - Requires compatible types
  • Function<Integer, Integer> multiplyByTwo = x -> x * 2;
  • Function<Integer, Integer> squareThenDouble = multiplyByTwo.compose(square);
  • int res2 = squareThenDouble.apply(3); // square(3)=9, multiplyByTwo(9)=18
  • 3. Binary Functional Interfaces

When operations require two input arguments, Java provides binary functional interface variants. Notice that there is no BiSupplier in Java because a method cannot return multiple independent return values.

  • Interface SAM Signature Return Type Key Methods
  • BiConsumer<T, U> void accept(T t, U u) void andThen(BiConsumer)
  • BiPredicate<T, U> boolean test(T t, U u) boolean and() , or() , negate()
  • BiFunction<T, U, R> R apply(T t, U u) R andThen(Function)

Warning

BiFunction has NO compose() method : While Function<T, R> provides both compose() and andThen() , BiFunction<T, U, R> provides only andThen(Function<? super R, ? extends V> after) . It does not support compose() because a preceding function would need to produce two return values simultaneously to feed T and U into BiFunction .

4. Operator Interfaces: UnaryOperator & BinaryOperator

Operators are specializations of Function and BiFunction where the input argument types and return type are identical. // UnaryOperator<T> extends Function<T, T>

  • @FunctionalInterface
  • public interface UnaryOperator<T> extends Function<T, T> {
  • static <T> UnaryOperator<T> identity() {
  • return t -> t;
  • }
  • }
  • // BinaryOperator<T> extends BiFunction<T, T, T>
  • @FunctionalInterface
  • public interface BinaryOperator<T> extends BiFunction<T, T, T> {
  • static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator) {
  • Objects.requireNonNull(comparator);
  • return (a, b) -> comparator.compare(a, b) <= 0 ? a : b;
  • }
  • static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) {
  • Objects.requireNonNull(comparator);
  • return (a, b) -> comparator.compare(a, b) >= 0 ? a : b;
  • }
  • } UnaryOperator<String> toUpper = String::toUpperCase;
  • String result = toUpper.apply("java 21"); // "JAVA 21"
  • BinaryOperator<Integer> adder = (a, b) -> a + b;
  • int sum = adder.apply(10, 20); // 30
  • BinaryOperator<String> longest = BinaryOperator.maxBy(Comparator.comparingInt(String::length));
  • String winner = longest.apply("Elephant", "Cat"); // "Elephant"
  • 5. Primitive Functional Interface Specializations

To avoid the severe memory and CPU performance overhead of boxing and unboxing primitives ( int ↔ \leftrightarrow ↔ Integer , double ↔ \leftrightarrow ↔ Double , long ↔ \leftrightarrow ↔ Long ), java.util.function includes specialized interfaces for the three primary numerical primitive types: int , long , and double (plus BooleanSupplier ).

1. Primitive Suppliers, Consumers, and Predicates

  • Interface SAM Signature Method Name
  • IntSupplier int getAsInt() getAsInt()
  • LongSupplier long getAsLong() getAsLong()
  • DoubleSupplier double getAsDouble() getAsDouble()
  • BooleanSupplier boolean getAsBoolean() getAsBoolean()
  • IntConsumer void accept(int value) accept(int)
  • LongConsumer void accept(long value) accept(long)
  • DoubleConsumer void accept(double value) accept(double)
  • IntPredicate boolean test(int value) test(int)
  • LongPredicate boolean test(long value) test(long)
  • DoublePredicate boolean test(double value) test(double)
  • 2. Primitive Function Categories
  • Category A: Takes Primitive, Returns Object ( XFunction<R> )
  • IntFunction<R> : R apply(int value)
  • LongFunction<R> : R apply(long value)
  • DoubleFunction<R> : R apply(double value)
  • Category B: Takes Object, Returns Primitive ( ToXFunction<T> )
  • ToIntFunction<T> : int applyAsInt(T value)
  • ToLongFunction<T> : long applyAsLong(T value)
  • ToDoubleFunction<T> : double applyAsDouble(T value)
  • Category C: Takes Primitive, Returns Primitive ( XToYFunction - 9 combinations)
  • IntToLongFunction : long applyAsLong(int value)
  • IntToDoubleFunction : double applyAsDouble(int value)
  • LongToIntFunction : int applyAsInt(long value)
  • LongToDoubleFunction : double applyAsDouble(long value)
  • DoubleToIntFunction : int applyAsInt(double value)
  • DoubleToLongFunction : long applyAsLong(double value)
  • IntUnaryOperator : int applyAsInt(int operand)
  • LongUnaryOperator : long applyAsLong(long operand)
  • DoubleUnaryOperator : double applyAsDouble(double operand)
  • Category D: Two-Argument Primitive Variants
  • ObjIntConsumer<T> : void accept(T t, int value)
  • ObjLongConsumer<T> : void accept(T t, long value)
  • ObjDoubleConsumer<T> : void accept(T t, double value)
  • ToIntBiFunction<T, U> : int applyAsInt(T t, U u)
  • ToLongBiFunction<T, U> : long applyAsLong(T t, U u)
  • ToDoubleBiFunction<T, U> : double applyAsDouble(T t, U u)
  • IntBinaryOperator : int applyAsInt(int left, int right)
  • LongBinaryOperator : long applyAsLong(long left, long right)

DoubleBinaryOperator : double applyAsDouble(double left, double right) // Primitive Specializations in Practice

  • IntToDoubleFunction half = x -> x / 2.0;
  • double halfResult = half.applyAsDouble(7); // 3.5
  • ObjIntConsumer<List<String>> listAppender = (list, index) -> list.add("Item #" + index);
  • List<String> storage = new ArrayList<>();
  • listAppender.accept(storage, 42); // storage contains ["Item #42"]
  • ToIntFunction<String> strLength = String::length;
  • int len = strLength.applyAsInt("Oracle Java 21"); // 14
  • 6. Comprehensive Summary Table for the 1Z0-830 Exam
  • Interface Name Number of Args SAM Method Name Return Type Boxed or Primitive
  • Supplier<T> 0 get() T Reference
  • BooleanSupplier 0 getAsBoolean() boolean Primitive
  • IntSupplier 0 getAsInt() int Primitive
  • Consumer<T> 1 accept(T t) void Reference
  • IntConsumer 1 accept(int v) void Primitive
  • BiConsumer<T, U> 2 accept(T t, U u) void Reference
  • ObjIntConsumer<T> 2 accept(T t, int v) void Hybrid
  • Predicate<T> 1 test(T t) boolean Reference input
  • IntPredicate 1 test(int v) boolean Primitive input
  • BiPredicate<T, U> 2 test(T t, U u) boolean Reference inputs
  • Function<T, R> 1 apply(T t) R Reference
  • IntFunction<R> 1 apply(int v) R Primitive input
  • ToIntFunction<T> 1 applyAsInt(T t) int Primitive output
  • IntToDoubleFunction 1 applyAsDouble(int v) double Primitive to Primitive
  • BiFunction<T, U, R> 2 apply(T t, U u) R Reference
  • ToIntBiFunction<T, U> 2 applyAsInt(T t, U u) int Primitive output
  • UnaryOperator<T> 1 apply(T t) T Reference
  • IntUnaryOperator 1 applyAsInt(int v) int Primitive
  • BinaryOperator<T> 2 apply(T t1, T t2) T Reference
  • IntBinaryOperator 2 applyAsInt(int a, int b) int Primitive

Loading diagram... Functional Interface Taxonomy and Composition Combinators