Java 8 - Functional Interfaces

Introduction

 
In the last article, while implementing lambda expressions we came across the word functional interfaces and this article explains what, why, and implementation of functional interfaces in our production code.
 
Functional Interface was introduced with Java 8, which is an interface that has only a single abstract method. Multi abstract methods in the same functional interface will return in error. Conversely, if you have an interface that has only a single abstract method, then that will effectively be a functional interface and can be used anywhere where a functional interface is eligible to be used.
 
This is present under the java.util.Function package and includes something around 40+ functional interfaces which can be directly implemented in your code. Some functional interfaces are used repeatedly, which are shown below:
 
 Fig 1 : Functional Interfaces
 
Each functional interface has a single abstract method, called functional method. For that functional interface, implementation can be passed around lambda expressions and method references.
 
@functionalInterface Annotation
 
For any interface, to be a functional interface we use an annotation i.e @functionalInterface.
 
Functional Interface annotation can be used to explicitly specify that a given interface is to be treated as a functional interface, then the compiler will check and give a compile-time error in case the annotated interface doesn’t satisfy the basic condition of qualifying as a functional Interface.
 
Here, each interface is explained one by one below:
 

Consumer Functional Interface

 
 
Fig 1.1 : Different Consumer Functional Interfaces
 
Consumer<T> is an inbuilt functional interface introduced in java 8 in the java.util.Function package, where T is the type of input to the operation. This is a functional interface that can be used with a lambda expression and method reference.
 
This interface can be used in all contexts where an object needs to be consumed i.e it takes an input, and some operation is performed on the object without returning any result.
  1. @FunctionalInterface  
  2. public interface Consumer<T> {  
  3.    void accept(T t);  
  4. }   
Where accept() method is the primary abstract method of consumer interface, its functional descriptor T->() i.e accept() method takes an input type of T and returns no value.
All other consumers functional interface differ in a way or other i.e,
 
BiConsumer<T,U> functional interface, here T, U is the type of the input to the operation, and represents an operation that accepts two input arguments and returns no result.
DoubleConsumer, IntConsumer andLongConsumer functional interface, these all are similar to some extent as represents an operation that accepts a single double/int/ long-valued argument and returns no result.
 
ObjIntConsumer<T>, ObjLongConsumer<T>, ObjDoubleConsumer<T> functional interfaces, these all functional interfaces are the same and only differ in their return type value of the method. This represents an operation which accepts an object valued and an int/long/double - valued argument and returns no result.
 
Example
  1. package Functional_Interface;  
  2. import java.util.Arrays;  
  3. import java.util.List;  
  4. import java.util.function.Consumer;  
  5. public class ConsumerDemo {  
  6.     public static void main(String[] args) {  
  7.         List < String > al = Arrays.asList("abcba""asffsa""mnbvcvbnm""klnff""fweffqqewf""dwfew""ffwf""dsvsd");  
  8.         Consumer < List < String >> cons = list - > {  
  9.             for (int i = 0; i < al.size(); i++) {  
  10.                 StringBuffer sb = new StringBuffer(al.get(i));  
  11.                 al.set(i, sb.reverse().toString());  
  12.             }  
  13.         };  
  14.         cons.accept(al); //consumer interface function  
  15.         // Using Method Reference to print elements  
  16.         al.forEach(System.out::println);  
  17.     }  
  18. }  

Predicate Functional Interface

 
 
Fig 1.2 Different Predicate Functional Interfaces
 
Predicate<T> is an inbuilt functional interface introduced in java 8 in the java.util.Function package, where T is the type of input to the operation. This is a functional interface that can be used with a lambda expression and method reference.
 
This interface can be used where an object needs to be evaluated for a given test condition anda boolean value needs to be returned based on whether a condition is met or not. The user need not to define his/her own predicate-type functional interface.
  1. @FunctionalInterface  
  2. public interface Predicate < T > {  
  3.     boolean test(T t);  
  4. }   
Where test() method is the primary abstract method of predicate interface, its functional descriptor T->() i.e test() method takes an input type of T and returns a boolean result based on whether a condition is met or not.
 
All other predicate functional interfaces differ in a way or other i.e,
 
BiPredicate<T,U> functional interface, here T, U is the type of the input to the operation and represents an operation that accepts two input arguments and returns a boolean result based on whether a condition is met or not.
 
IntPredicate, DoublePredicate and LongPredicate functional interface, these all are much similar to some extent as represents an operation that accepts a single int/double/long-valued argument and returns a boolean result based on whether a condition is met or not.
 
Example
  1. package Functional_Interface;  
  2. import java.util.Arrays;  
  3. import java.util.List;  
  4. import java.util.function.Predicate;  
  5. public class PredicateDemo {  
  6.     public static void main(String[] args) {  
  7.         List < String > list = Arrays.asList("abcba""asffsa""mnbvcvbnm""klnff""fweffqqewf""dwfew""ffwf""dsvsd");  
  8.         String[] str = (String[]) list.toArray();  
  9.         Predicate < String > p = s - > {  
  10.             StringBuffer sb1 = new StringBuffer(s);  
  11.             StringBuffer sb2 = new StringBuffer(s);  
  12.             sb2.reverse();  
  13.             if (sb2.toString().equals(sb1.toString())) return true;  
  14.             return false;  
  15.         };  
  16.         //Stream API is used to print elements  
  17.         Arrays.stream(str).filter(p).forEach(System.out::println);  
  18.     }  
  19. }  

Supplier Functional Interface

 
Fig 1.3 Different Supplier Functional Interfaces
 
Supplier<T> is an inbuilt functional interface introduced in java 8 in the java.util.Function package, where T is the type of input to the operation. This is a functional interface which can be used with lambda expression and method reference.
 
This interface can be used where there is no input argument and output is expected.
  1. @FunctionalInterface  
  2. public interface Supplier < T > {  
  3.     T get();  
  4. }   
Where get() method is the primary abstract method of predicate interface, its functional descriptor () -> T i.e get() method takes no input type and returns the output of type T.
All other supplier functional interface differ in a way or other i.e,
 
Boolean functional interface represents an operation that accepts no argument and returns a boolean-valued result. It has a functional method as getAsBoolean().
 
IntSupplier, DoubleSupplier and LongSupplier functional interface, these all are much similar to some extent as represents an operation that accepts no argument and returns a boolean-valued result.
  1. package Functional_Interface;  
  2. import java.util.function.Supplier;  
  3. public class SupplierDemo {  
  4.     public static void main(String[] args) {  
  5.         Supplier < Double > s1 = () - > {  
  6.             return Math.random() * 4;  
  7.         };  
  8.         System.out.println(s1.get());  
  9.     }  
  10. }   

Function Functional Interfaces

 
Fig 1.4 : Different Function Functional Interfaces
 
Function<T,R> is an inbuilt functional interface introduced in java 8 in the java.util.Function package, where T is generic input type and R is the type of output of the operation. This is a functional interface which can be used with a lambda expression and method reference.
 
This interface is more of a generic one that takes one argument and produces a result of type R. This interface is commonly used with the Stream.map method.
  1. @FunctionalInterface  
  2. public interface Function < T, R > {  
  3.     R apply(T t);  
  4. }   
Where apply() method is the primary abstract method of predicate interface, its functional descriptor T->() i.e apply() method takes one input argument and returns the output of type R.
 
All other function functional interface differ in a way or other i.e,
 
BiFunction<T,U,R> functional interface, here T,U are generic input type and R is a type of output of operation and represents an operation that accepts one argument and returns a result of type R. It has a functional method as apply().
 
IntFunction<R>, DoubleFunction<R> and LongFunction<R> functional interface, these all are much similar to some extent as represents an operation that accepts int/double/long-valued argument and returns a result of type R.
  1. package Functional_Interface;  
  2. import java.util.function.Function;  
  3. public class FunctionInterfaceDemo {  
  4.     public static void main(String[] args) {  
  5.         int x = 4;  
  6.         //using lambda expression  
  7.         Function < Integer, Integer > fn1 = (num) - > (x * x);  
  8.         System.out.println(fn1.apply(x));  
  9.         String s = "Welcome to C# Corner";  
  10.         //using lambda expression  
  11.         Function < String, Integer > fn2 = (s1) - > s1.length();  
  12.         System.out.println(fn2.apply(s));  
  13.     }  
  14. }  

What did we learn?

 
After reading this article, users have a thorough knowledge of what functional interfaces are and their usage with existing Java versions.
 
Note
While trying to work with any feature of java 8 remember to use JDK 1.8 or higher else these concepts and code will not work.
 

Summary

 
As discussed above we have learned,
  • What are the functional Interfaces?
  • Where to use functional interfaces.
  • Different types of functional interfaces and more...