Pages

Wednesday, July 10, 2019

Java 8 Functional Interfaces (FI)

1. Overview

In this tutorial, We'll learn about Functional Interface added to Java 8. Functional Interface is abbreviated as FI.

These Functional Interfaces are used extensively in Lambda Expressions.

Please read article on "A Complete Guide to Lambda Expressions"

If you have a basic understanding of Lambda's that will help in using Functional Interface(FI) properly. But, We will discuss in short about Lambda's.

Java 8 Functional Interfaces (FI)


We will cover the following concepts in this article.


  • Intro to Lambda
  • Lambda Examples
  • Functional Interface Definition
  • @FunctionalInterface annotation
  • Built-in FI's
  • Types of Functional Interfaces with examples




2. Lambda Expression and Examples


Before Lambda's introduction, We were using anonymous inner classes widely in our applications. Lambda Expression denotes a function or method without any name to it. But it takes method arguments, body, and valid return type.

We will write a program to create a Thread using Runnable interface using an anonymous inner class.

2.1 Runnable with Anonymous Inner Class


We will be demonstrating anonymous inner class usage with the Runnable interface. The runnable interface has a method called run() which should have the thread implementation.

package com.java.w3schools.blog.java8.functional;

public class ThreadCreation {

 public static void main(String[] args) {

  Thread t = new Thread(new Runnable() {
   @Override
   public void run() {
    System.out.println("Thread execution started.");
   }
  });

 }
}

t.start();

Output:

A Runnable anonymous inner class object is created and passed to Thread class. Invoking t.start() will initiate the thread and starts execution. See the below output.

Thread execution started.

2.2 Runnable with Lambda's


In the above program, using an anonymous inner class for the Runnable interface is having many lines of code. But, the same code can be reduced to a few lines using new java 8 lambda expressions syntax.

Just see the below code.

Thread lambdaThread = new Thread(() -> System.out.println("Lambda Trhead exection started."));
lambdaThread.start();

Now, the new code written in lambda is in a single line. Removed all boilerplate code and converted it to more readable as well as easy to maintain.


3. Functional Interface Definition


In simple words, If the interface has only one abstract method then it is called Function Interface(FI).
All of FI's implementations can be used with Lambda.

You already know many Function Interface's that are available before Java 8 also. They are Comparable, Runnable, Callable, etc. But these are not declared as FunctionalInterface.

3.1 @FunctionalInterface Annotation


We can define any interface @FunctionalInterface annotation but it shows compile error if not having exactly one abstract method.

This annotation is very helpful to avoid accidentally adding additional abstract methods or removing the existing ones. Hence, stops breaking other code.

Note: This annotation is not mandatory and it is optional.

@FunctionalInterface
interface RunParellel {
boolean run();
}

We can explicitly identify a functional interface using the @FunctionalInterface annotation as above.

Compiler error : "The target type of this expression must be a functional interface"

Note: To create a custom Functional Interface, We must annotate the interface with @FunctionalInterface. That's all, From now this can be used with Lambda.

4. Built-in Functional Interfaces


Java 8 introduced a lot of Functional Interfaces as part of JDK 8. All are bundled into package java.util.function and total 43 functional interfaces.

All these are divided into 4 categories.

A) Suppliers
B) Consumers
C) Predicates
D) Functions

All these functional interfaces are having exactly only one abstract method (these may have static or default and private methods)

Private methods in interfaces are introduced in Java 9.

Note: The abstract method inside a Functional Interface is called as Functional Method.

We'll be using this "Functional Method" terminology in this tutorial from now onwards.

Built-in all FI's in java.util.function package

4.1 Suppliers


Suppliers always return some value and never takes an argument.

Supplier is a Functional Interface which has get() functional method. This is present in java.util.function package.

T get()

Example:

package com.java.w3schools.blog.java8.functional;

import java.util.function.Supplier;

/**
 * Supplier Interface in Java with Examples
 * 
 * @author Venkatesh
 *
 */
public class SupplierExample {

 public static void main(String[] args) {

// This Supper always return a random value
  Supplier randomValue = () -> Math.random();
  System.out.println(randomValue.get());
 }
}

Output:

0.8141135990476829

4.2 Consumers


Consumers consume values. java.util.function.Consumer’s has a functional method accept(). This FI always takes an argument and never returns anything.

This is just consuming the value or object passing to accept() functional method.

Consumer has two methods. One abstract method and one defalut method.

Functional Method: void accept(T t)
Default Method: default Consumer andThen(Consumer after)

Example:

package com.java.w3schools.blog.java8.functional;

import java.util.function.Consumer;

/**
 * Consumer Interface in Java with Examples
 * 
 * @author venkatesh
 *
 */
public class ConsumerExample {
 public static void main(String[] args) {
  Consumer consumer = (String value) -> {
   System.out.println(value.toUpperCase());
  };
  consumer.accept("Welcome to Java W3schools blog");
 }
}

Output:

WELCOME TO JAVA W3SCHOOLS BLOG

4.3 Predicates


Predicates test things and this is used to perform logical operations.

java.util.function.Predicate’s have a functional method test().

This FI has total of 5 methods.

1 Functional Method:

boolean test(T t)

3 default methods:

default Predicate and(Predicate other)
default Predicate negate()
default Predicate or(Predicate other)

1 static method:

static  Predicate isEqual(Object targetRef)

These 4 default methods are very helpfull to perform logical operations such as and, or, negate or equal operations.

Note: Predicate always take an input argument and returns a boolean value. Inside this method, We can perform the requried operations. Finally, It returns true or false.

Example:

package com.java.w3schools.blog.java8.functional;

import java.util.function.Predicate;

/**
 * Predicate Interface in Java with Examples
 * 
 * @author Venkatesh
 *
 */

public class PredicateExample {
 public static void main(String[] args) {

  Predicate predicate = (String str) -> str.contains("Java");

  boolean isJavaDeveloper = predicate.test("Jhon is a Java Developer");

  if (isJavaDeveloper) {
   System.out.println("Yes, Jhon is a Java Developer. He can develop Java based web applications");
  } else {
   System.out.println("Jhob is not a Java developer.");
  }
 }
}

Output:

Yes, Jhon is a Java Developer. He can develop Java based web applications

Here, test() method takes String as argument and checks that string has a word "Java". If the string has Java then it returns true. Otherwise returns false.
In our example, the input string has a Java word. This predicate returns true.

4.4 Functions


Represents a function that accepts one argument and produces a result.

You can think of functions as the most generic of the functional interfaces. java.util.function.Function’s functional method, apply().

Interface Function

Type Parameters:

T - the type of the input to the function
R - the type of the result of the function 

This has 1 functional method, 2 default methods and 1 static method.

R apply(T t)


2 default methods:

default  Function compose(Function before)
default  Function andThen(Function after)

1 static method:

static  Function identity()

Example:

package com.java.w3schools.blog.java8.functional;

import java.util.function.Function;

/**
 * Function Interface in Java with Examples
 * 
 * @author Venkatesh
 *
 */
class FunctionExample {
 public static void main(String[] args) {
  Function function = (String input) -> input.substring(5);
  String output = function.apply("This is a test Function interface in java 8");
  System.out.println(output);
 }
}

Output:

is a test Function interface in java 8

In this example, It taken input type and Output type as String. In other words, apply() method takes String as input and returns String value.

5. Conclusion


In this tutorial, We've seen What is Function Interface(FI) and how FI's are used with Lambda Expression.

How to define a custom functional interface.

What are the Built-in FI's are in Java 8? Discussed 4 types of FI's such as Supplier, Consumer, Predicate, and Function.

All examples shown in this article are over GitHub.

No comments:

Post a Comment

Please do not add any spam links in the comments section.