Table of Contents
A functional interface in Java is an interface with a single abstract method. This allows it to be used as the target type for a lambda expression or method reference. It is also known as SAM (Single Abstract Method) interface. It can have any number of default and static methods but a single abstract method.
Java uses @FunctionalInterface
annotation to mark an interface as functional although it is optional but is better to follow the standard for good coding practice.
By using functional interfaces and lambda expressions, we can write more concise and readable code. It also enables us to pass behavior as a method argument, making our code more flexible and modular.
For example, consider a class that sorts a list of Person
objects. Without using functional interfaces and lambda expressions, we would need to create a separate Comparator
class for each sort order.
import java.util.ArrayList; import java.util.Collections; import java.util.List; public class Person { private String firstName; private String lastName; private int age; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Person(String firstName, String lastName, int age) { super(); this.firstName = firstName; this.lastName = lastName; this.age = age; } public static void main(String[] args) { List<Person> people = new ArrayList<>(); people.add(new Person("John", "Doe", 30)); people.add(new Person("Jane", "Doe", 25)); people.add(new Person("Jim", "Smith", 35)); Collections.sort(people, new AgeComparator()); System.out.println(people); } } class AgeComparator implements java.util.Comparator<Person> { @Override public int compare(Person a, Person b) { return a.getAge() - b.getAge(); } }
With functional interfaces and lambda expressions, we can simplify the code by passing the sort order as a lambda expression directly to the sort method.
mport java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; public class Person { private String firstName; private String lastName; private int age; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Person(String firstName, String lastName, int age) { super(); this.firstName = firstName; this.lastName = lastName; this.age = age; } public static void main(String[] args) { List<Person> people = new ArrayList<>(); people.add(new Person("John", "Doe", 30)); people.add(new Person("Jane", "Doe", 25)); people.add(new Person("Jim", "Smith", 35)); Collections.sort(people, (a, b) -> a.getAge() - b.getAge()); System.out.println(people); } }
In this example, the lambda expression (a, b) -> a.getAge() - b.getAge()
implements the compare method of the Comparator interface, and can be used to sort a list of Person objects by age.
Java 8 provides several built-in functional interfaces some of which are listed below.
For example, the java.util.function.Consumer
functional interface defines a single abstract method accept which takes an object and returns no result.
It can be used to represent an operation that takes an object and performs some action on it, such as printing the object to the console.
mport java.util.function.Consumer; public class Main { public static void main(String[] args) { Consumer<String> consumer = s -> System.out.println(s); consumer.accept("Hello World"); } }
Output:
Hello World
Another example is the java.util.function.Predicate
functional interface which defines a single abstract method test that takes an object and returns a boolean. It can be used to represent a condition or a test that takes an object and returns a true or false result.
import java.util.function.Predicate; public class Main { public static void main(String[] args) { Predicate<String> predicate = s -> s.length() > 5; System.out.println(predicate.test("Hello")); System.out.println(predicate.test("World")); } }
In this example, the lambda expression s -> s.length() > 5
implements the test method of the Predicate interface, and can be used to test whether a String has a length greater than 5.
Conclusion
The functional interface is a new feature introduced in Java 8 with to support functional programming. You can implement its abstract method as a lambda expression which is again good for writing functional code.