Java.util.function Package

·

13 min read

Consumer

The Consumer<T> interface in the java.util.function package is a functional interface that represents an operation that takes a single input argument of type T and returns no result. It has a single abstract method called accept, which defines the operation to be performed on the input argument. Here are the methods of the Consumer<T> interface:

1.accept(T t):

This is the primary abstract method of the Consumer interface. It takes a single argument of type T and performs the operation defined by the consumer.

Example:

Consumer<String> printUpperCase = s -> System.out.println(s.toUpperCase());
printUpperCase.accept("hello");  // Output: HELLO

2.andThen(Consumer<? super T> after):

This is a default method that returns a composed Consumer that performs, in sequence, the operations of the current Consumer followed by the afterConsumer.

Example:

Consumer<String> printLength = s -> System.out.println("Length: " + s.length());
Consumer<String> combinedConsumer = printUpperCase.andThen(printLength);
combinedConsumer.accept("world");  // Output: WORLD, Length: 5

In the example, combinedConsumer is created by chaining the printUpperCase and printLength consumers using the andThen method.

Summary:

  • accept(T t): Performs the defined operation on the given input argument.

  • andThen(Consumer<? super T> after): Returns a composed Consumer that performs the operations of the current Consumer followed by the operations of the afterConsumer.

These methods make Consumer<T> a versatile interface for defining and combining operations that consume a single argument. The accept method is where the main operation is defined, and andThen allows for chaining multiple consumers to create more complex behavior.

Supplier

The Supplier<T> interface in the java.util.function package is a functional interface representing a supplier of results. It has a single abstract method get(), which takes no arguments and produces a result of type T. Additionally, it has a few default methods that provide convenient ways to combine and manipulate suppliers. Here are the methods of the Supplier<T> interface:

1.get():

This is the primary method of the Supplier interface. It takes no arguments and produces a result of type T. It represents the operation of supplying a value.

Example:

import java.util.function.Supplier;

public class SupplierExample {
    public static void main(String[] args) {
        // Creating a Supplier that supplies a constant value
        Supplier<String> constantSupplier = () -> "Hello, World!";

        // Using the get method to obtain the supplied value
        String result = constantSupplier.get();
        System.out.println(result);  // Output: Hello, World!
    }
}

2.andThen(Supplier<? extends T> after):

This is a default method that returns a composed Supplier that first obtains a value from the current Supplier and then obtains a value from the afterSupplier.

Example:

import java.util.function.Supplier;

public class SupplierExample {
    public static void main(String[] args) {
        // Creating two suppliers
        Supplier<String> prefixSupplier = () -> "Hello, ";
        Supplier<String> suffixSupplier = () -> "World!";

        // Chaining suppliers using andThen
        Supplier<String> combinedSupplier = prefixSupplier.andThen(suffixSupplier);

        // Obtaining the result from the chained supplier
        String result = combinedSupplier.get();
        System.out.println(result);  // Output: Hello, World!
    }
}

Summary:

  • get(): Produces a result of type T. It represents the operation of supplying a value.

  • andThen(Supplier<? extends T> after): Returns a composed Supplier that first obtains a value from the current Supplier and then obtains a value from the afterSupplier.

The Supplier interface is useful in scenarios where you need to lazily generate or obtain a value, and the get method is invoked when the value is actually needed. The andThen method provides a way to chain multiple suppliers to create more complex behavior.

Function

The Function<T, R> interface in the java.util.function package is a functional interface representing a function that takes an argument of type T and produces a result of type R. It has several useful methods in addition to its primary method apply(T t). Here are the methods of the Function<T, R> interface:

1.apply(T t):

This is the primary method of the Function interface. It takes an argument of type T and produces a result of type R. It represents the operation of applying the function to the input.

Example:

import java.util.function.Function;

public class FunctionExample {
    public static void main(String[] args) {
        // Creating a Function that converts a String to its length
        Function<String, Integer> stringLengthFunction = s -> s.length();

        // Using the apply method to obtain the result
        int length = stringLengthFunction.apply("Hello");
        System.out.println(length);  // Output: 5
    }
}

2.andThen(Function<? super R, ? extends V> after):

This is a default method that returns a composed function that first applies the current function to its input and then applies the after function to the result.

Example:

import java.util.function.Function;

public class FunctionExample {
    public static void main(String[] args) {
        // Creating two functions
        Function<String, Integer> stringLengthFunction = s -> s.length();
        Function<Integer, String> intToStringFunction = i -> "Length: " + i;

        // Chaining functions using andThen
        Function<String, String> combinedFunction = stringLengthFunction.andThen(intToStringFunction);

        // Obtaining the result from the chained function
        String result = combinedFunction.apply("Hello");
        System.out.println(result);  // Output: Length: 5
    }
}

3.compose(Function<? super V, ? extends T> before):

This is a default method that returns a composed function that first applies the before function to its input and then applies the current function to the result.

Example:

import java.util.function.Function;

public class FunctionExample {
    public static void main(String[] args) {
        // Creating two functions
        Function<String, Integer> stringLengthFunction = s -> s.length();
        Function<Integer, String> intToStringFunction = i -> "Length: " + i;

        // Chaining functions using compose
        Function<String, String> combinedFunction = intToStringFunction.compose(stringLengthFunction);

        // Obtaining the result from the chained function
        String result = combinedFunction.apply("Hello");
        System.out.println(result);  // Output: Length: 5
    }
}

Summary:

  • apply(T t): Applies the function to the input and produces a result.

  • andThen(Function<? super R, ? extends V> after): Returns a composed function that first applies the current function and then applies the after function to the result.

  • compose(Function<? super V, ? extends T> before): Returns a composed function that first applies the before function and then applies the current function to the result.

The Function<T, R> interface is frequently used in functional programming scenarios, such as when working with the Stream API or when transforming data from one form to another. The andThen and compose methods allow for the composition of functions to create more complex transformations.

BiFunction

The BiFunction<T, U, R> interface in the java.util.function package is a functional interface representing a function that takes two arguments of types T and U, and produces a result of type R. It extends the Function<T, R> interface and introduces two additional methods. Here are the methods of the BiFunction<T, U, R> interface:

1.apply(T t, U u):

This is the primary method of the BiFunction interface. It takes two arguments of types T and U and produces a result of type R. It represents the operation of applying the function to the input arguments.

Example:

import java.util.function.BiFunction;

public class BiFunctionExample {
    public static void main(String[] args) {
        // Creating a BiFunction that concatenates two strings
        BiFunction<String, String, String> concatenateFunction = (s1, s2) -> s1 + s2;

        // Using the apply method to obtain the result
        String result = concatenateFunction.apply("Hello, ", "World!");
        System.out.println(result);  // Output: Hello, World!
    }
}

2.andThen(Function<? super R, ? extends V> after):

This is a default method inherited from the Function interface. It returns a composed function that first applies the current BiFunction and then applies the after function to the result.

Example:

import java.util.function.BiFunction;
import java.util.function.Function;

public class BiFunctionExample {
    public static void main(String[] args) {
        // Creating a BiFunction that adds two integers
        BiFunction<Integer, Integer, Integer> addFunction = (a, b) -> a + b;

        // Creating a Function that converts an integer to its string representation
        Function<Integer, String> intToStringFunction = i -> "Result: " + i;

        // Chaining functions using andThen
        Function<Integer, String> combinedFunction = addFunction.andThen(intToStringFunction);

        // Obtaining the result from the chained function
        String result = combinedFunction.apply(3, 4);
        System.out.println(result);  // Output: Result: 7
    }
}

3.compose(Function<? super V, ? extends T> before):

This is a default method inherited from the Function interface. It returns a composed function that first applies the before function to its input and then applies the current BiFunction to the result.

Example:

import java.util.function.BiFunction;
import java.util.function.Function;

public class BiFunctionExample {
    public static void main(String[] args) {
        // Creating a BiFunction that multiplies two integers
        BiFunction<Integer, Integer, Integer> multiplyFunction = (a, b) -> a * b;

        // Creating a Function that converts an integer to its string representation
        Function<Integer, String> intToStringFunction = i -> "Result: " + i;

        // Chaining functions using compose
        Function<Integer, String> combinedFunction = intToStringFunction.compose(multiplyFunction);

        // Obtaining the result from the chained function
        String result = combinedFunction.apply(3, 4);
        System.out.println(result);  // Output: Result: 12
    }
}

Summary:

  • apply(T t, U u): Applies the function to the input arguments and produces a result.

  • andThen(Function<? super R, ? extends V> after): Returns a composed function that first applies the current BiFunction and then applies the after function to the result.

  • compose(Function<? super V, ? extends T> before): Returns a composed function that first applies the before function and then applies the current BiFunction to the result.

The BiFunction<T, U, R> interface is often used in scenarios where a function takes two inputs and produces a result, such as when performing operations on pairs of elements or when transforming data from one form to another. The andThen and compose methods allow for the composition of functions to create more complex transformations.

Predicate

The Predicate<T> interface in the java.util.function package is a functional interface representing a predicate (boolean-valued function) of one argument. It has several useful methods in addition to its primary method test(T t). Here are the methods of the Predicate<T> interface:

1.test(T t):

This is the primary method of the Predicate interface. It takes an argument of type T and returns a boolean result. It represents the operation of testing the given argument.

Example:

import java.util.function.Predicate;

public class PredicateExample {
    public static void main(String[] args) {
        // Creating a Predicate that checks if a string is empty
        Predicate<String> isEmpty = s -> s.isEmpty();

        // Using the test method to check the condition
        boolean result = isEmpty.test("Hello");
        System.out.println(result);  // Output: false
    }
}

2.and(Predicate<? super T> other):

This is a default method that returns a composed predicate that represents a logical AND of this predicate and another. The test method of the composed predicate returns true only if both predicates evaluate to true.

Example:

import java.util.function.Predicate;

public class PredicateExample {
    public static void main(String[] args) {
        // Creating two Predicates
        Predicate<String> isNotEmpty = s -> !s.isEmpty();
        Predicate<String> startsWithHello = s -> s.startsWith("Hello");

        // Combining Predicates using and
        Predicate<String> combinedPredicate = isNotEmpty.and(startsWithHello);

        // Using the test method with the combined predicate
        boolean result = combinedPredicate.test("Hello, World!");
        System.out.println(result);  // Output: true
    }
}

3.or(Predicate<? super T> other):

This is a default method that returns a composed predicate that represents a logical OR of this predicate and another. The test method of the composed predicate returns true if at least one of the predicates evaluates to true.

Example:

import java.util.function.Predicate;

public class PredicateExample {
    public static void main(String[] args) {
        // Creating two Predicates
        Predicate<String> containsJava = s -> s.contains("Java");
        Predicate<String> endsWithExclamation = s -> s.endsWith("!");

        // Combining Predicates using or
        Predicate<String> combinedPredicate = containsJava.or(endsWithExclamation);

        // Using the test method with the combined predicate
        boolean result = combinedPredicate.test("I love Java!");
        System.out.println(result);  // Output: true
    }
}

4.negate():

This is a default method that returns a predicate that represents the logical negation of this predicate.

Example:

import java.util.function.Predicate;

public class PredicateExample {
    public static void main(String[] args) {
        // Creating a Predicate
        Predicate<Integer> isEven = n -> n % 2 == 0;

        // Creating the negation of the Predicate
        Predicate<Integer> isOdd = isEven.negate();

        // Using the test method with the negated predicate
        boolean result = isOdd.test(5);
        System.out.println(result);  // Output: true
    }
}

Summary:

  • test(T t): Tests the given argument against the predicate and returns a boolean result.

  • and(Predicate<? super T> other): Returns a composed predicate representing a logical AND of this predicate and another.

  • or(Predicate<? super T> other): Returns a composed predicate representing a logical OR of this predicate and another.

  • negate(): Returns a predicate representing the logical negation of this predicate.

The Predicate<T> interface is commonly used in scenarios where you need to express boolean conditions, such as filtering elements in a collection or validating input values. The combination methods (and, or, negate) provide powerful tools for building complex predicate conditions.

UnaryOperator

The UnaryOperator<T> interface in the java.util.function package is a functional interface representing an operation on a single operand of type T that produces a result of the same type T. It extends the Function<T, T> interface and inherits its methods. Here are the methods of the UnaryOperator<T> interface:

1.apply(T t) (Inherited from Function<T, T>):

This is the primary method of the UnaryOperator interface. It takes an argument of type T and produces a result of the same type T. It represents the operation of applying the unary operator to the input.

Example:

import java.util.function.UnaryOperator;

public class UnaryOperatorExample {
    public static void main(String[] args) {
        // Creating a UnaryOperator that squares an integer
        UnaryOperator<Integer> squareOperator = n -> n * n;

        // Using the apply method to obtain the result
        int result = squareOperator.apply(5);
        System.out.println(result);  // Output: 25
    }
}

2.identity() (Static method):

This is a static method of the UnaryOperator interface. It returns a unary operator that always returns its input argument.

Example:

import java.util.function.UnaryOperator;

public class UnaryOperatorExample {
    public static void main(String[] args) {
        // Using the identity method to obtain a unary operator
        UnaryOperator<String> identityOperator = UnaryOperator.identity();

        // Using the apply method with the identity operator
        String result = identityOperator.apply("Hello");
        System.out.println(result);  // Output: Hello
    }
}

The identity method returns a unary operator that acts as the identity function, meaning it returns the input argument unchanged.

Summary:

  • apply(T t) (Inherited from Function<T, T>): Applies the unary operator to the input and produces a result.

  • identity() (Static method): Returns a unary operator that always returns its input argument.

The UnaryOperator<T> interface is often used in scenarios where you need to represent operations that transform a value of a certain type into another value of the same type. The identity method is particularly useful when you need a simple unary operator that doesn't modify the input.

BinaryOperator

The BinaryOperator<T> interface in the java.util.function package is a functional interface representing an operation on two operands of type T that produces a result of the same type T. It extends the BiFunction<T, T, T> interface and inherits its methods. Here are the methods of the BinaryOperator<T> interface:

1.apply(T t, T u) (Inherited from BiFunction<T, T, T>):

This is the primary method of the BinaryOperator interface. It takes two arguments of type T and produces a result of the same type T. It represents the operation of applying the binary operator to the input operands.

Example:

import java.util.function.BinaryOperator;

public class BinaryOperatorExample {
    public static void main(String[] args) {
        // Creating a BinaryOperator that adds two integers
        BinaryOperator<Integer> addOperator = (a, b) -> a + b;

        // Using the apply method to obtain the result
        int result = addOperator.apply(3, 4);
        System.out.println(result);  // Output: 7
    }
}

2.minBy(Comparator<? super T> comparator) (Static method):

This is a static method of the BinaryOperator interface. It returns a binary operator that returns the minimum of two elements according to the specified comparator.

Example:

import java.util.function.BinaryOperator;
import java.util.Comparator;

public class BinaryOperatorExample {
    public static void main(String[] args) {
        // Creating a BinaryOperator that finds the minimum of two integers
        BinaryOperator<Integer> minOperator = BinaryOperator.minBy(Comparator.naturalOrder());

        // Using the apply method to obtain the result
        int result = minOperator.apply(3, 7);
        System.out.println(result);  // Output: 3
    }
}

3.maxBy(Comparator<? super T> comparator) (Static method):

This is a static method of the BinaryOperator interface. It returns a binary operator that returns the maximum of two elements according to the specified comparator.

Example:

import java.util.function.BinaryOperator;
import java.util.Comparator;

public class BinaryOperatorExample {
    public static void main(String[] args) {
        // Creating a BinaryOperator that finds the maximum of two integers
        BinaryOperator<Integer> maxOperator = BinaryOperator.maxBy(Comparator.naturalOrder());

        // Using the apply method to obtain the result
        int result = maxOperator.apply(3, 7);
        System.out.println(result);  // Output: 7
    }
}

Summary:

  • apply(T t, T u) (Inherited from BiFunction<T, T, T>): Applies the binary operator to the input operands and produces a result.

  • minBy(Comparator<? super T> comparator) (Static method): Returns a binary operator that returns the minimum of two elements according to the specified comparator.

  • maxBy(Comparator<? super T> comparator) (Static method): Returns a binary operator that returns the maximum of two elements according to the specified comparator.

The BinaryOperator<T> interface is often used in scenarios where you need to represent operations that combine two values of a certain type into another value of the same type. The minBy and maxBy methods provide convenient ways to create binary operators that find the minimum or maximum of two elements based on a comparator.