Functional Interfaces in Java 8
Overview
Functional interfaces are a new feature introduced in Java 8. They are interfaces that have a single abstract method, and can thus be implemented using lambda expressions, method references, or anonymous classes. This makes them a key component of the functional programming paradigm in Java.
Definition
A functional interface is defined with the help of the @FunctionalInterface annotation, although this annotation is optional. The presence of a single abstract method is what makes an interface functional.
Example: Defining a Functional Interface
@FunctionalInterface
interface MyFunctionalInterface {
void myMethod();
}
Built-in Functional Interfaces
Java 8 provides several built-in functional interfaces in the java.util.function package. Some of the most commonly used ones are:
Predicate<T>: Represents a predicate (boolean-valued function) of one argument.Function<T, R>: Represents a function that accepts one argument and produces a result.Supplier<T>: Represents a supplier of results.Consumer<T>: Represents an operation that accepts a single input argument and returns no result.UnaryOperator<T>: Represents an operation on a single operand that produces a result of the same type as its operand.BinaryOperator<T>: Represents an operation upon two operands of the same type, producing a result of the same type as the operands.
Example: Using a Built-in Functional Interface
Using Predicate to filter a list of strings:
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class PredicateExample {
public static void main(String[] args) {
List names = Arrays.asList("Alice", "Bob", "Charlie", "David");
Predicate startsWithA = name -> name.startsWith("A");
List namesStartingWithA = names.stream()
.filter(startsWithA)
.collect(Collectors.toList());
System.out.println(namesStartingWithA);
}
}
Lambda Expressions with Functional Interfaces
Lambda expressions are a natural fit for functional interfaces. They allow you to provide the implementation of the abstract method defined by the functional interface.
Example: Implementing a Functional Interface using a Lambda Expression
@FunctionalInterface
interface MyFunctionalInterface {
void myMethod();
}
public class LambdaExample {
public static void main(String[] args) {
MyFunctionalInterface myFunc = () -> System.out.println("Hello, World!");
myFunc.myMethod();
}
}
Method References with Functional Interfaces
Method references can also be used to provide implementations for functional interfaces, making the code even more concise and readable.
Example: Implementing a Functional Interface using a Method Reference
import java.util.function.Consumer;
public class MethodReferenceExample {
public static void main(String[] args) {
Consumer printer = System.out::println;
printer.accept("Hello, Method Reference!");
}
}
Custom Functional Interfaces
In addition to the built-in functional interfaces, you can create your own custom functional interfaces to meet specific needs in your application.
Example: Creating and Using a Custom Functional Interface
@FunctionalInterface
interface Calculator {
int calculate(int a, int b);
}
public class CustomFunctionalInterfaceExample {
public static void main(String[] args) {
Calculator add = (a, b) -> a + b;
Calculator subtract = (a, b) -> a - b;
System.out.println("Addition: " + add.calculate(5, 3));
System.out.println("Subtraction: " + subtract.calculate(5, 3));
}
}
Conclusion
Functional interfaces in Java 8 are a powerful feature that enable functional programming paradigms. By using built-in and custom functional interfaces along with lambda expressions and method references, you can write more concise and readable code.
