Skip to main content

Functional Interface in Java

Functional Interface in Java

In this article, we will learn what is a Functional Interface in Java, Also we are going to have a look at how we can create it and use them.
So, let's start this tutorial with the definition of the functional interface.

What is Functional Interface in Java?

A Functional Interface is an interface that contains only one abstract method. It can have one or more default methods but there should only be only one abstract method. Let see an example of a Functional Interface in Java.
@FunctionalInterface
interface BookConstraint{
     boolean test(Book book);
}
Note: Functional interface in java can be instantiated by the lambda expressions, method references, or anonymous class. We will see later how we can instantiate the Functional Interface in java later in this post.

@FunctionalInterface Annotation

In the above example, the interface is marked with @FunctionalInterface annotation. The @FunctionalInterface annotation (Introduced in Java 8) can be used to optionally mark an interface. Please keep that note, it also generates the compile-time error if the below-mentioned conditions are not satisfying.
The conditions are :
  • The interface must contain only one abstract method.
  • The abstract method should not be a default method in case of Java 8.

Java also provides some built-in Functional Interface like :

  • The runnable interface of java.lang package contains only one abstract method which is the run() method.
  • Comparator<T> interface of the java.util package contains only one abstract method which is the compare(T obj1, T obj2) method.
  • ActionListener interface of java.awt.event package contains only one abstract method which is actionPerformed(ActionEvent e) method.

How to Instantiate a Functional Interface in Java?

Using Anonymous Inner Class

Anonymous class is an inner class used to instantiate any Interface in Java, not just Functional Interfaces.

Example 1: Instantiate our BookConstraint Functional Interface using Anonymous Inner Class

BookConstraint javaBookConstraint = new BookConstraint() {
     @Override
     public boolean test(Book book) {
         return book.getTitle().contains("Java");
     }
};
Book book = new Book();
book.setTitle("Learn Java");
boolean isJavaBook = javaBookConstraint.test(book);
if (isJavaBook) {
     System.out.println("This is a Java Book");
}

Example 2: Instantiate Runnable Functional Interface using Anonymous Inner Class

Runnable runnable = new Runnable() {
     @Override
     public void run() {
         System.out.println("Instantiate Runnable using Anonymous Inner Class");
     }
};
Thread thread = new Thread(runnable);
thread.start();

Example 3: Instantiate Comparator Functional Interface using Anonymous Inner Class

Comparator<String> stringLengthComparator = new Comparator<String>() {
     @Override
     public int compare(String str1, String str2) {
         return str1.length() - str2.length();
     }
};
List<String> list = Arrays.asList(
          "Runnable", "Comparator", "ActionListener", "BookConstraint");
Collections.sort(list, stringLengthComparator);
// To Print the List in Sorted Order according to it's length
list.forEach(System.out::println);

Using Lambda Expressions

Lambda Expressions are introduced in Java 8 can also be used to instantiate the Functional Interface. Read this article to know more about them: Lambda Expression in Java

Example 1: Instantiate our BookConstraint Functional Interface using Lambda Expressions Java

BookConstraint javaBookConstraint = book -> book.getTitle().contains("Java");
Book book = new Book();
book.setTitle("Learn Java");
boolean isJavaBook = javaBookConstraint.test(book);
if (isJavaBook) {
     System.out.println("This a Java Book");
}

Example 2: Instantiate Runnable Functional Interface using Lambda Expressions Java

Runnable runnable = () -> System.out.println("Instantiate Runnable using Anonymous Inner Class");
Thread thread = new Thread(runnable);
thread.start();

Example 3: Instantiate Comparator Functional Interface using Lambda Expressions Java

Comparator<String> stringComparator = (str1, str2) -> str1.length() - str2.length();
List<String> list = Arrays.asList(
          "Runnable", "Comparator", "ActionListener", "BookConstraint");
Collections.sort(list, stringComparator);
// To Print the List in Sorted Order
list.forEach(System.out::println);

New Functional Interface introduced in Java 8

Java 8 introduced various built-in Functional Interfaces, that can be used in common programming practices like to write method definition, conditional expressions, etc. These interfaces are part of the java.util.function package. There are a lot of functional interfaces defined in this package, we will discuss a few of them in this tutorial which are used very commonly, and discuss the rest of them in some other article.

Functions

The Function<T,R> is a Functional Interface in Java 8 is declared in java.util.function package, which is used to write in-line methods. Inline methods can be considered as when the definition of a method is in-lined within the other method.
The one and only abstract method declared in this interface are the apply() method, and this method takes an argument of T type and transforms it into the R type. Basically, this interface is treated as a function that takes an argument and converts it into the result.
@FunctionalInterface
public interface Function<T, R> {
     R apply(T t);
}
The Lambda expression attaches to the Function will become the definition of the apply() method. For Examples :

Example 1: Function that takes a Book as an argument and returns its title

Function<Book, String> getBookTitle = book -> book.getTitle();
String title = getBookTitle.apply(book);

Example 2: Function that takes a String as argument and converts it into Uppercase

Function<String, String> toUpperCase = str -> str.toUpperCase();
String upperCaseTitle = toUpperCase.apply(title);
Note: We can also combine two or more Functions by using andThen() method and they will run into the sequence.

Example 3: Function that takes a Book as an argument then fetch its title and then convert it into Uppercase

Function<Book, String> getBookTitle = book -> book.getTitle();
Function<String, String> toUpperCase = str -> str.toUpperCase();
Function<Book, String> getBookTitleInUpperCase = getBookTitle.andThen(toUpperCase);
String upperCaseTitle = getBookTitleInUpperCase.apply(book);

Predicates

The Predicate<T> is a Functional Interface in Java 8 is declared in java.util.function package, which is used to write conditional expressions or boolean-valued function. The only abstract method declared in this interface is the test() method. This method takes an argument of T type and perform some tests on the argument and return true or false.
@FunctionalInterface
public interface Predicate<T> {
     boolean test(T t);
}
The Lambda expression attaches to the Predicate will become the definition of the test() method. For Examples :

Example 1: Predicate that takes a Book as an argument and checks whether it is a java book or not

Predicate<Book> isJavaBookPredicate = book -> book.getTitle().contains("Java");
boolean result = isJavaBookPredicate.test(book);

Example 2: Predicate that takes a Book as an argument and checks whether it's price under 500 or not

Predicate<Book> isUnder500Predicate = book -> book.getPrice() <= 500;
boolean result = isUnder500Predicate.test(book);
Note: We can also combine two or more Predicates by and/or methods
Predicate<Book> isJavaBookPredicate = book -> book.getTitle().contains("Java");
Predicate<Book> isUnder500Predicate = book -> book.getPrice() <= 500;
Predicate<Book> isJavaBookAndUnder500Predicate = isJavaBookPredicate.and(isUnder500Predicate);
Predicate<Book> eitherJavaBookOrUnder500Predicate = isJavaBookPredicate.or(isUnder500Predicate);

Suppliers

The Supplier<T> is a Functional Interface in Java 8 is declared in java.util.function package is used to write suppliers which supply an output without any input value. The only abstract method declared in this interface is the get() method. This method doesn't take any argument but returns an output of the T type.
@FunctionalInterface
public interface Supplier<T> {
     T get();
}
The Lambda expression attach with the Supplier will become the definition of the get() method. For Examples :

Example 1: Supply a new book

Supplier<Book> bookSupplier = () -> new Book();
Book book = bookSupplier.get();
book.setTitle("Learn Java");
book.setPrice(450);

Example 2: Supply a new book with title and price

Supplier<Book> bookSupplier = () -> new Book("Learn Java", 450);
Book book = bookSupplier.get();

Example 3: Supply a new book with the title and price using the method

// Any Random method
Book createBook(String Title, int Price){
      return new Book(title, price);
}
--------------------------------------------------------------------------
Supplier<Book> bookSupplier = () -> createBook("Learn Java", 450);
Book book = bookSupplier.get();

Consumers

The Consumer<T> is a Functional Interface in Java 8 is declared in java.util.function package is used to write a function that consumes something i.e., the argument passed from outside. The only abstract method declared in this interface is the accept() method. This method takes an argument of T type, consumes it but returns the void output.
@FunctionalInterface
public interface Consumer<T> {
     void accept(T t);
}
The Lambda expression attaches with the Consumer will become the definition of the accept() method. For Examples :

Example 1: Consumes a book

Consumer<Book> bookConsumer = book -> System.out.println(book.getTitle() + " : " + book.getPrice());

Example 2: Consumes a book using method

// Any Random method
void printBook(Book book)
      System.out.println(book.getTitle() + " : " + book.getPrice());
}
--------------------------------------------------------------------------
Consumer<Book> bookConsumer = book -> printBook(book);

The consumer used by forEach() of a list of book

// Any Random method
void printBook(Book book)
      System.out.println(book.getTitle() + " : " + book.getPrice());
}
--------------------------------------------------------------------------
List<Book> listOfBooks = new ArrayList<>();
listOfBooks.add("Learn Java" , 450);
listOfBooks.add("Learn C++" , 280);
listOfBooks.add("Learn Android" , 750);
Consumer<Book> bookConsumer = book -> printBook(book);
listOfBooks.forEach(bookConsumer);

Conclusion

In this article, we have what is a functional interface in java, we have seen what they are, how to create using multiple ways, and how to use them. Also, we have learned what are some pre-defined functional interface that can be used in our day-to-day programming.

Related Posts:

Lambda Expression in Java
Java Optional

Comments