Java Functional Interfaces

In Java, a functional interface is an interface that has only one abstract method. Functional interfaces are used to represent functional types, which can be used as the assignment target for lambda expressions or method references.

Java provides several built-in functional interfaces in the java.util.function package, which can be used to write functional code with less boilerplate. Some of the commonly used functional interfaces in Java include:

  1. Consumer<T> – Accepts a single argument of type T and returns no result.
  2. Supplier<T> – Represents a supplier of results.
  3. Predicate<T> – Represents a predicate (boolean-valued function) of one argument.
  4. Function<T, R> – Represents a function that accepts one argument of type T and produces a result of type R.
  5. UnaryOperator<T> – Represents an operation on a single operand that produces a result of the same type as its operand.
  6. BinaryOperator<T> – Represents an operation upon two operands of the same type, producing a result of the same type as the operands.

For example, here is an example of using a lambda expression with a functional interface to implement a simple operation:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(name -> System.out.println("Hello, " + name));

In this example, the forEach method of the List interface takes a Consumer functional interface as its argument, which is implemented using a lambda expression that takes a String argument and prints a greeting message.

Java Predefined-Functional Interfaces:

Java has several predefined functional interfaces in the java.util.function package that can be used to write functional code with less boilerplate. These interfaces represent common functional types that are frequently used in Java programming. Some of the commonly used predefined functional interfaces in Java include:

  1. Supplier<T> – Represents a supplier of results. It has a single method get() that returns a value of type T.
  2. Consumer<T> – Accepts a single argument of type T and returns no result. It has a single method accept(T t).
  3. Predicate<T> – Represents a predicate (boolean-valued function) of one argument. It has a single method test(T t) that returns a boolean value.
  4. Function<T, R> – Represents a function that accepts one argument of type T and produces a result of type R. It has a single method apply(T t) that returns a value of type R.
  5. UnaryOperator<T> – Represents an operation on a single operand that produces a result of the same type as its operand. It has a single method apply(T t) that takes a value of type T and returns a value of the same type.
  6. BinaryOperator<T> – Represents an operation upon two operands of the same type, producing a result of the same type as the operands. It has a single method apply(T t1, T t2) that takes two values of type T and returns a value of the same type.
  7. BiFunction<T, U, R> – Represents a function that accepts two arguments of types T and U, and produces a result of type R. It has a single method apply(T t, U u) that takes two arguments of types T and U, and returns a value of type R.
  8. BiPredicate<T, U> – Represents a predicate (boolean-valued function) of two arguments. It has a single method test(T t, U u) that takes two arguments of types T and U, and returns a boolean value.
  9. Consumer<T> – Represents an operation that accepts two input arguments and returns no result. It has a single method accept(T t, U u) that takes two arguments of types T and U, and returns no result.

These predefined functional interfaces can be used to write functional code in a concise and expressive way. For example, the following code snippet uses the Predicate functional interface to filter a list of integers:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
Predicate<Integer> even = n -> n % 2 == 0;
List<Integer> evenNumbers = numbers.stream()
                                   .filter(even)
                                   .collect(Collectors.toList());

In this example, the even predicate is defined using a lambda expression that checks whether a given integer is even or not. The filter method of the Stream interface takes a Predicate functional interface as its argument, which is implemented using the even predicate. The resulting stream is then collected into a new list using the collect method. The resulting list contains only the even numbers from the original list.