Java 8 Functional Interfaces
A functional interface is an interface that has exactly one abstract method, but can have multiple non-abstract methods.
Functional interfaces can be implicitly converted to lambda expressions.
Lambda expressions and method references (which can also be considered as lambda expressions).
For example, if you define a functional interface as follows:
@FunctionalInterface
interface GreetingService
{
void sayMessage(String message);
}
Then you can use a lambda expression to represent an implementation of this interface (note: before Java 8, this was typically done using anonymous classes):
GreetingService greetService1 = message -> System.out.println("Hello " + message);
Functional interfaces provide a friendly support for lambda expressions in existing functions.
Functional interfaces that were available before JDK 1.8:
- java.lang.Runnable
- java.util.concurrent.Callable
- java.security.PrivilegedAction
- java.util.Comparator
- java.io.FileFilter
- java.nio.file.PathMatcher
- java.lang.reflect.InvocationHandler
- java.beans.PropertyChangeListener
- java.awt.event.ActionListener
- javax.swing.event.ChangeListener
Functional interfaces added in JDK 1.8:
- java.util.function
The java.util.function package contains many classes to support functional programming in Java. Some of the functional interfaces in this package include:
No. | Interface & Description |
---|---|
1 | BiConsumer<T,U> Represents an operation that accepts two input parameters and returns no result. |
2 | BiFunction<T,U,R> Represents a function that accepts two input parameters and returns a result. |
3 | BinaryOperator<T> Represents an operation upon two operands of the same type, returning a result of the same type as the operands. |
4 | BiPredicate<T,U> Represents a predicate (boolean-valued function) of two arguments. |
5 | BooleanSupplier Represents a supplier of boolean-valued results. |
6 | Consumer<T> Represents an operation that accepts a single input parameter and returns no result. |
7 | DoubleBinaryOperator Represents an operation upon two double-valued operands and producing a double-valued result. |
8 | DoubleConsumer Represents an operation that accepts a single double-valued argument and returns no result. |
9 | DoubleFunction<R> Represents a function that accepts a double-valued argument and produces a result. |
10 | DoublePredicate Represents a predicate of one double-valued argument. |
11 | DoubleSupplier Represents a supplier of double-valued results. |
12 | DoubleToIntFunction Accepts a double-valued argument and produces an int-valued result. |
13 | DoubleToLongFunction Accepts a double-valued argument and produces a long-valued result. |
14 | DoubleUnaryOperator Represents an operation on a single double-valued operand that produces a double-valued result. |
15 | Function<T,R> Represents a function that accepts one argument and produces a result. |
16 | IntBinaryOperator Represents an operation upon two int-valued operands and produces an int-valued result. |
17 | IntConsumer Represents an operation that accepts a single int-valued argument and returns no result. |
18 | IntFunction<R> Represents a function that accepts an int-valued argument and produces a result. |
19 | IntPredicate Represents a predicate of one int-valued argument. |
20 | IntSupplier Represents a supplier of int-valued results. |
21 | IntToDoubleFunction Represents a function that accepts an int-valued argument and produces a double-valued result. |
22 | IntToLongFunction Represents a function that accepts an int-valued argument and produces a long-valued result. |
23 | IntUnaryOperator accepts a parameter of type int and returns a value of type int. |
24 | LongBinaryOperator accepts two parameters of type long and returns a value of type long. |
25 | LongConsumer accepts an input parameter of type long and has no return value. |
26 | LongFunction<R> accepts an input parameter of type long and returns a result. |
27 | LongPredicate accepts an input parameter of type long and returns a boolean result. |
28 | LongSupplier has no parameters and returns a value of type long. |
29 | LongToDoubleFunction accepts an input of type long and returns a result of type double. |
30 | LongToIntFunction accepts an input of type long and returns a result of type int. |
31 | LongUnaryOperator accepts a parameter of type long and returns a value of type long. |
32 | ObjDoubleConsumer<T> accepts an object type and a double type input parameter and has no return value. |
33 | ObjIntConsumer<T> accepts an object type and an int type input parameter and has no return value. |
34 | ObjLongConsumer<T> accepts an object type and a long type input parameter and has no return value. |
35 | Predicate<T> accepts an input parameter and returns a boolean result. |
36 | Supplier<T> has no parameters and returns a result. |
37 | ToDoubleBiFunction<T,U> accepts two input parameters and returns a result of type double. |
38 | ToDoubleFunction<T> accepts an input parameter and returns a result of type double. |
39 | ToIntBiFunction<T,U> accepts two input parameters and returns a result of type int. |
40 | ToIntFunction<T> accepts an input parameter and returns a result of type int. |
41 | ToLongBiFunction<T,U> accepts two input parameters and returns a result of type long. |
42 | ToLongFunction<T> accepts an input parameter and returns a result of type long. |
43 | UnaryOperator<T> accepts a parameter of type T and returns a value of type T. |
Functional Interface Example
The Predicate<T> interface is a functional interface that accepts an input parameter T and returns a boolean result.
This interface contains various default methods to combine Predicates into other complex logic (such as: and, or, negate).
This interface is used to test whether an object is true or false.
We can understand the usage of the functional interface Predicate<T> through the following example (Java8Tester.java):
Java8Tester.java File
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
public class Java8Tester {
public static void main(String args[]){
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
// Predicate<Integer> predicate = n -> true
// n is a parameter passed to the test method of the Predicate interface
// If n exists, the test method returns true
System.out.println("Print all numbers:");
// Pass parameter n
eval(list, n->true);
// Predicate<Integer> predicate1 = n -> n%2 == 0
// n is a parameter passed to the test method of the Predicate interface
// If n%2 is 0, the test method returns true
System.out.println("Print all even numbers:");
eval(list, n-> n%2 == 0 );
// Predicate<Integer> predicate2 = n -> n > 3
This is an English translation of the provided text:
// n is a parameter passed to the test method of the Predicate interface
// The test method returns true if n is greater than 3
System.out.println("Output all numbers greater than 3:");
eval(list, n -> n > 3);
}
public static void eval(List<Integer> list, Predicate<Integer> predicate) {
for (Integer n : list) {
if (predicate.test(n)) {
System.out.println(n + " ");
}
}
}
}
Executing the above script, the output is:
$ javac Java8Tester.java
$ java Java8Tester
Output all data:
1
2
3
4
5
6
7
8
9
Output all even numbers:
2
4
6
8
Output all numbers greater than 3:
4
5
6
7
8
9