Study guide

7.2 Standard Functional Interfaces in `java.util.function`

Oracle Java SE 17 Developer Certified Professional 1Z0-829

Track your progress as you read

Finished sections get a check mark.

1 Introduction: The 1Z0-829 Exam

About the Java SE 17 Developer (1Z0-829) Exam

2 Chapter 1: Java Fundamentals & Language Basics

1.1 Primitive Types, Literals, Wrapper Classes, and Type Promotion/Casting 1.2 Local Variable Type Inference (`var`) Rules and Scoping 1.3 Operators, Precedence, Evaluation Order, and Short-Circuit Evaluation 1.4 Text Blocks, String Immutability, and StringBuilder APIs

3 Chapter 2: Program Flow & Decision Constructs

2.1 Conditional Branching with if/else and the Ternary Operator 2.2 Switch Statements and Switch Expressions 2.3 Iteration Constructs, Loop Control, and Branching Labels

4 Chapter 3: Object-Oriented Design & Class Mechanics

3.1 Class Declarations, Field/Method Signatures, and Access Modifiers 3.2 Constructors, Overloading, Initialization Order, and Garbage Collection 3.3 Inheritance, Method Overriding, Polymorphism, and `super`/`this` 3.4 Abstract Classes, Static Members, and Object Methods (`equals`, `hashCode`, `toString`)

5 Chapter 4: Advanced OOP: Interfaces, Records & Sealed Types

4.1 Interface Architecture: Default, Static, and Private Methods 4.2 Enumerations: Constants, Constructors, Methods, and Custom Bodies 4.3 Records: Canonical/Compact Constructors, Components, and Immutability 4.4 Sealed Classes and Interfaces: `permits`, Hierarchy Constraints, and Modifiers

6 Chapter 5: Pattern Matching & Nested Types

5.1 Pattern Matching for `instanceof` and Flow Scoping Mechanics 5.2 Nested Types: Member Inner, Static Nested, Local, and Anonymous Classes 5.3 Defensive Programming, Immutability Patterns, and Validation

7 Chapter 6: Generics, Collections & Arrays

6.1 Generic Classes, Interfaces, Methods, and Type Erasure 6.2 Bounded Type Parameters and Wildcards (PECS Rule) 6.3 Collections Framework: List, Set, Queue, and Deque APIs 6.4 The Map Interface, Sorting, Comparable, and Comparator 6.5 Arrays: Declaration, Initialization, Multidimensional Arrays, and the Arrays Utility Class

8 Chapter 7: Functional Programming & Lambda Expressions

7.1 Functional Interfaces and Lambda Syntax Rules 7.2 Standard Functional Interfaces in `java.util.function` 7.3 Method References: Static, Bound, Unbound, and Constructor References

9 Chapter 8: The Stream API

8.1 Stream Lifecycle: Creation, Pipeline Architecture, and Lazy Evaluation 8.2 Intermediate Stream Operations: Filtering, Mapping, Sorting, and Slicing 8.3 Terminal Stream Operations: Reduction, Matching, Finding, and Collecting 8.4 Primitive Streams (`IntStream`, `LongStream`, `DoubleStream`) and Numeric Statistics

10 Chapter 9: Advanced Streams & Collectors

9.1 The Optional Class: Safe Null Handling, Transformation, and Chaining 9.2 The Collectors API: Downstream Reductions, Grouping, and Partitioning 9.3 Parallel Streams: Fork/Join Pool, Spliterators, and Concurrency Pitfalls

11 Chapter 10: Exception Handling

10.1 The Java Exception Hierarchy: Checked vs. Unchecked Exceptions and Errors 10.2 Exception Constructs: `try-catch-finally`, Multi-Catch, and Rethrowing 10.3 Try-With-Resources, `AutoCloseable`, Suppressed Exceptions, and Custom Exceptions

12 Chapter 11: Date/Time API & Localization

11.1 Date and Time Core Types: `LocalDate`, `LocalTime`, `LocalDateTime` 11.2 Timestamps, Intervals, and Durations: `Instant`, `Period`, and `Duration` 11.3 Time Zones, Daylight Saving Time (DST) Offsets, and `ZonedDateTime` 11.4 Internationalization and Localization: `Locale`, `ResourceBundle`, and Formatters 11.5 Formatting and Parsing Messages, Numbers, Percentages, and Localized Dates

13 Chapter 12: Java Platform Module System (JPMS)

12.1 Module Architecture, `module-info.java`, and Module Paths 12.2 Module Directives: `requires`, `requires transitive`, `exports`, and Qualified Exports 12.3 Reflection, Deep Encapsulation, `opens`, and Open Modules 12.4 Services in JPMS (`uses`, `provides...with`), Migration Paths, and Tooling (`jlink`, `jdeps`) 12.5 Compiling and Packaging Code: Non-Modular JARs, Modular JARs, and Migration Strategies

14 Chapter 13: Concurrency & Multithreading

13.1 Thread Fundamentals, `Runnable`, `Callable`, and Thread Lifecycle 13.2 Memory Visibility, `volatile`, Intrinsic Locks, and Synchronization 13.3 The Concurrency Framework: `ExecutorService`, Thread Pools, and `Future` 13.4 Concurrent Collections, Atomic Variables, Explicit Locks, and `CompletableFuture`

15 Chapter 14: Java I/O and NIO.2

14.1 Classical I/O: Byte and Character Streams, Readers, Writers, and Buffering 14.2 Object Serialization, `Serializable`, `transient`, and `serialVersionUID` 14.3 NIO.2 Architecture: `Path`, `Paths`, and Basic `Files` Operations 14.4 Advanced NIO.2: Directory Walking, Streams (`Files.lines`, `walk`), and `WatchService`

16 Chapter 15: Accessing Databases with JDBC

15.1 JDBC Architecture, Drivers, `DriverManager`, and `DataSource` Connections 15.2 SQL Execution: `Statement`, `PreparedStatement`, and `CallableStatement` 15.3 `ResultSet` Navigation, Data Types, and Transaction Management (Commit, Rollback, Savepoints)

17 Chapter 16: Annotations & the Java Logging API

16.1 Standard Annotations: @Override, @FunctionalInterface, @Deprecated, @SuppressWarnings, and @SafeVarargs 16.2 Java Logging API Basics: Logger, Levels, Handlers, and Configuration

7.2 Standard Functional Interfaces in `java.util.function`

Key Takeaways Explain This Topic AI

The java.util.function package organizes functional interfaces into four primary families: Predicate<T> (boolean test), Consumer<T> (void accept), Function<T, R> (R apply), and Supplier<T> (T get).

Two-parameter extensions include BiPredicate<T, U> , BiConsumer<T, U> , and BiFunction<T, U, R> ; there is no BiSupplier in the standard library.

UnaryOperator<T> extends Function<T, T> and BinaryOperator<T> extends BiFunction<T, T, T> , ensuring that parameter types and the return type match exactly.

Primitive specializations eliminate boxing and unboxing overhead for int, long, and double; primitive suppliers use specialized getters (such as getAsInt() and getAsBoolean()) rather than get().

Default combinator methods enable functional chaining: Predicate supports and(), or(), and negate(); Function provides andThen() and compose(); and Consumer offers andThen().

Last updated: October 2026

7.2 Standard Functional Interfaces in java.util.function

Prior to Java 8, libraries frequently declared redundant single-method interfaces for callbacks, comparisons, and transformations. To standardize functional programming across the Java runtime, Java provides the java.util.function package containing 43 general-purpose functional interfaces. On the 1Z0-829 exam, you must recognize the four core functional families, their two-parameter extensions, operator specializations, primitive adaptations, and default composition methods.

The Four Foundational Families

Every functional interface in java.util.function derives conceptually from four core archetypes categorized by their input arity and return type: +---------------------------------------+

  • | Core Functional Interface Families |
  • +---------------------------------------+
  • |
  • +-----------------+--------------+---------------+-----------------+
  • | | | |
  • v v v v
  • Predicate<T> Consumer<T> Function<T, R> Supplier<T>
  • boolean test(T) void accept(T) R apply(T) T get()
  • [Condition/Filter] [Side-effect/Action] [Transformation] [Factory/Generator]
  • 1. Predicate<T> : boolean test(T t)

Evaluates a condition against an argument of type T and returns a primitive boolean . Primarily used for filtering, validation, and matching. Predicate<String> isLong = s -> s != null && s.length() > 5;

  • boolean result = isLong.test("Enterprise"); // true
  • 2. Consumer<T> : void accept(T t)

Accepts an argument of type T and executes a side-effect without returning a value. Primarily used for logging, printing, and mutating state. Consumer<String> printer = s -> System.out.println("Log: " + s);

  • printer.accept("Transaction successful");
  • 3. Function<T, R> : R apply(T t)

Transforms an input argument of type T into a result of type R . Forms the backbone of mapping operations in streams. Function<String, Integer> lengthFinder = s -> s.length();

  • Integer len = lengthFinder.apply("Oracle"); // 6
  • 4. Supplier<T> : T get()

Takes no arguments ( () ) and returns an instance of type T . Used for lazy evaluation, object factories, and generating values on demand. Supplier<LocalDate> today = () -> LocalDate.now();

  • LocalDate currentDate = today.get();
  • Two-Parameter Extensions and Operators

Java extends the foundational families to handle two input arguments, as well as homogenous transformations.

Two-Parameter Variants

Interface SAM Signature Functional Purpose

BiPredicate<T, U> boolean test(T t, U u) Tests a condition involving two distinct input types.

BiConsumer<T, U> void accept(T t, U u) Consumes two arguments for side effects (e.g., Map.forEach ).

BiFunction<T, U, R> R apply(T t, U u) Transforms two input types T and U into return type R .

Note

Notice there is no BiSupplier in java.util.function . A supplier takes zero arguments; having a "two-input supplier" contradicts the definition of a supplier (a two-input producer is a BiFunction ).

Operators: Homogenous Functions

When a function's argument types and return type are identical, Java provides dedicated operator interfaces that extend Function and BiFunction :

UnaryOperator<T> : Extends Function<T, T> . Its single abstract method is T apply(T t) .

BinaryOperator<T> : Extends BiFunction<T, T, T> . Its single abstract method is T apply(T t1, T t2) . UnaryOperator<String> clean = s -> s.trim().toLowerCase();

String res = clean.apply(" Java 17 "); // "java 17"

  • BinaryOperator<Integer> max = (x, y) -> x >= y ? x : y;
  • Integer highest = max.apply(42, 99); // 99

Static utility methods on BinaryOperator :

BinaryOperator.minBy(Comparator<T> comp) : Returns a BinaryOperator<T> that selects the lesser of two elements according to the comparator.

BinaryOperator.maxBy(Comparator<T> comp) : Returns a BinaryOperator<T> that selects the greater of two elements.

Primitive Specializations

Using standard generic interfaces such as Function<Integer, Double> forces the JVM to continuously box and unbox primitives ( int ↔ \leftrightarrow ↔ Integer ), degrading performance and generating memory garbage. To optimize execution, java.util.function provides 34 specialized primitive interfaces centered on int , long , double , and boolean (the other 9 of its 43 interfaces are the generic ones such as Function and Supplier ).

Primitive Predicates, Consumers, and Suppliers

  • Interface SAM Signature Return Value Exam Notes
  • IntPredicate boolean test(int value) boolean Also LongPredicate , DoublePredicate
  • IntConsumer void accept(int value) void Also LongConsumer , DoubleConsumer

IntSupplier int getAsInt() int Method is getAsInt() , NOT get() !

  • LongSupplier long getAsLong() long Method is getAsLong()
  • DoubleSupplier double getAsDouble() double Method is getAsDouble()
  • BooleanSupplier boolean getAsBoolean() boolean Takes no args, returns primitive boolean

Warning

The Primitive Supplier Method Name Trap Generic Supplier<T> declares T get() . However, primitive suppliers do not declare get() . They declare getAsInt() , getAsLong() , getAsDouble() , and getAsBoolean() . Calling .get() on an IntSupplier causes a compile error!

Primitive Functions and Conversions

Primitive functions fall into three structural categories:

Primitive-to-Object Functions : Accept a primitive, return a generic reference R .

  • IntFunction<R> : R apply(int value)
  • LongFunction<R> : R apply(long value)
  • DoubleFunction<R> : R apply(double value)

Object-to-Primitive Functions : Accept a generic reference T , return a primitive.

  • ToIntFunction<T> : int applyAsInt(T value)
  • ToLongFunction<T> : long applyAsLong(T value)
  • ToDoubleFunction<T> : double applyAsDouble(T value)

Primitive-to-Primitive Conversions : Accept a primitive, return a different primitive.

  • 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)
  • Two-Argument Primitive Consumers and Operators

ObjIntConsumer<T> : void accept(T t, int value) (also ObjLongConsumer<T> , ObjDoubleConsumer<T> ).

IntUnaryOperator : int applyAsInt(int operand) (also LongUnaryOperator , DoubleUnaryOperator ).

IntBinaryOperator : int applyAsInt(int left, int right) (also LongBinaryOperator , DoubleBinaryOperator ).

Default and Static Combinator Methods

Many functional interfaces contain default and static methods that allow developers to compose and chain multiple behaviors together.

1. Predicate<T> Combinators

default Predicate<T> and(Predicate<? super T> other) : Evaluates this predicate, then evaluates other using short-circuiting logical AND ( && ).

default Predicate<T> or(Predicate<? super T> other) : Evaluates this predicate, then evaluates other using short-circuiting logical OR ( || ).

default Predicate<T> negate() : Inverts the predicate ( !test(t) ).

static <T> Predicate<T> isEqual(Object targetRef) : Returns a predicate testing whether arguments equal targetRef via Objects.equals() .

static <T> Predicate<T> not(Predicate<? super T> target) : Added in Java 11, returns the negation of the target predicate (ideal with method references: Predicate.not(String::isBlank) ). Predicate<String> nonNull = s -> s != null;

  • Predicate<String> nonBlank = s -> !s.isBlank();
  • Predicate<String> valid = nonNull.and(nonBlank);

// Short-circuiting behavior prevents NullPointerException:

boolean check = valid.test(null); // nonNull returns false -> nonBlank is NEVER called!

2. Function<T, R> Combinators

default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) : Applies this function first, and then applies after to the resulting value: after ( this ( x ) ) \text{after}(\text{this}(x)) after ( this ( x )) .

default <V> Function<V, R> compose(Function<? super V, ? extends T> before) : Applies before first, and then applies this to the resulting value: this ( before ( x ) ) \text{this}(\text{before}(x)) this ( before ( x )) .

static <T> Function<T, T> identity() : Returns a function that returns its input argument unchanged ( t -> t ). Function<Integer, Integer> multiplyBy2 = x -> x * 2;

Function<Integer, Integer> add10 = x -> x + 10;

  • // andThen: (x * 2) + 10
  • Function<Integer, Integer> f1 = multiplyBy2.andThen(add10);
  • System.out.println(f1.apply(5)); // (5 * 2) + 10 = 20
  • // compose: (x + 10) * 2
  • Function<Integer, Integer> f2 = multiplyBy2.compose(add10);
  • System.out.println(f2.apply(5)); // (5 + 10) * 2 = 30
  • 3. Consumer<T> Combinators

default Consumer<T> andThen(Consumer<? super T> after) : Executes this consumer, followed by after with the same input. If this throws an exception, after is not executed. Consumer<String> step1 = s -> System.out.print("Hello " + s);

  • Consumer<String> step2 = s -> System.out.println("!");
  • Consumer<String> combined = step1.andThen(step2);

combined.accept("Duke"); // Prints: Hello Duke!