Functional Programming and Lambda Expressions
Lesson -303.14 - Functional Interface and Lambda Expressions
Functional Interface and Lambda Expression
Learning Objectives: In this lesson, we will discuss and demonstrate functional interface and Lambda expressions. By the end of this session, learners will be able to:
Explain functional interfaces.
Demonstrate how to create and use functional interfaces.
Demonstrate how to implement functional interfaces.
Describe Lambda Expressions.
Demonstrate how to declare Lambda Expressions.
Describe built-in Lambda Expressions.
Table of Contents
Topic 1: Introduction to Functional Programming.
Topic 2a: Java Functional Interface.
Topic 2b: Instantiate Functional Interface.
Topic 2c: Generic Functional Abstraction.
Topic 3: Shorthand Notations for Functional Interface.
Topic 3a: Introduction to Lambda Expressions.
Topic 4: Built-in Functional Interfaces in Java.
Topic 4a: Functional Interface - Consumer<E>.
Topic 4b: Functional Interface - Supplier<E>.
Topic 4c: Functional Interface - Predicate<E>.
Topic 4d: Function interface - Functional<T,R>.
Topic 1: Introduction to Functional Programming
Functional Programming is a programming paradigm in which we try to bind everything in pure mathematical functions style. It is a declarative type of programming style. Functional Programming is also called declarative type programming style, and uses expressions instead of statements.
Topic 2a: Java Functional Interface
Each Functional Interface has a single abstract method (SAM) called the functional method. An interface that contains exactly a single abstract method means that the interface implementation will only represent one behavior. Apart from one abstract method, a functional interface can also have the following methods that do not count for defining it as a functional interface.
Default methods.
Static methods.
Public methods inherited from the Object Class. Conceptually, a functional interface has exactly one abstract method. Since default methods have an implementation, they are not abstract. You are free to add as many default methods and static methods as you like to your functional interface. In addition, a functional interface can also specify an Object's Class public methods, such as toString(), equal(), and others. Java 8 has a new package “java.util.function” that contains many functional interfaces.
Topic 2b: Instantiate Functional Interface
We can instantiate interfaces anonymously. The Anonymous class is a new “nameless” class that implements the interface and is instantiated anonymously. These kinds of interfaces are functional interfaces. Java 8 introduces the annotation @FunctionalInterface. The annotation is used to ensure that the functional interface cannot have more than one abstract method. If more than one abstract method is present, the compiler flags an error. However, it is not mandatory to use this annotation. If we remove the annotation, we are allowed to add another abstract method, but it will make the interface non-functional. In Java 8, functional interfaces can be represented using anonymous classes, Lambda expressions, method references, and constructor references.
Example 1: Functional Interface
Let’s build our first functional interface:
For the testing purpose, run your code. Your code should execute without any errors.
Example 1: Functional Interface (continued)
Let’s try to add another abstract method by the name of doSomeMoreWork();
Now run you code again. You will get a compiler error in your console as shown below:
Example 2: - Functional Interface - Anonymous Implementation Class
Step 1: Create an Interface named Human and add only one abstract method as shown below. This will be our Functional Interface.
Step 2: Create a regular class named NormalClass, and write the code below:
Example 3: Functional Interface
Let’s demonstrate one more example of functional interface. Step 1: Create an interface named FuncInterfaceExample and add the code below:
Step 2: Create a class named Calculator and add the code below:
Example: Generic - Functional Interface
In this example, we will demonstrate how to define a Generic Functional Interface that makes our program more dynamic.
Step 1: Create an interface named Generic_functionInterface. Specify one type parameter, as shown below code.
Step 2: Create a class named MycomparingClass. We are giving implementation of abstract method in this class. For the demonstration, we will see two implementations of the compare() method (abstract method):
Compare two Integers.
Compare two Strings.
Topic 3: Shorthand Notations for Functional Interface
JDK 8 introduces lambda expressions, which provides a shorthand notation for creating an instance of an anonymous inner class, implementing a functional interface.
Hands-On Activity
Create a simple calculator that processes or manipulates two variables:
Create an Interface named Calc that has a single abstract method named compute(). This method takes an array of integers.
Create a class called: MainEntry. In this class, implement the compute() method four times by using blocks to add, subtract, multiply, and divide. Then ask the user to enter a series of numbers, and ask what they would like to do with the numbers. In the case of compute() divide, only allow for two numbers. Hint: Use Generic.
Knowledge Check
What is a Functional Interface in Java?
What is a Default Method in an Interface?
Is it possible to define our own Functional Interface?
What is the @FunctionalInterface annotation?
Topic 3a: Introduction to Lambda Expressions
In general programming language, a
function
orlambda expression
is an anonymous (nameless) function that can be used to implement.Lambda expressions are nameless functions given as constant values and written exactly in the place where they are needed.
Lambda expressions are used primarily to define inline implementations of a
functional interface
.Lambda expressions eliminate the need of an anonymous class, and gives a very simple, yet powerful functional programming capability to Java.
Lambda expression
Syntax:
(parameter_list) -> {method_body: define programming logic here }
No name: This function is anonymous so we do not care about the name.
The parameters list:
Can receive zero, one, or more parameters.
Can be defined explicitly or inferred.
Empty parentheses = empty set of parameters.
No need to declare the type of its parameters.
The body - This is the main part of the function.
Can contain zero or more statements.
Just like loops, curly brackets are not mandatory for a single line.
More than one line/statement requires curly braces {}.
So NO need to use parentheses {} for functions with only one parameter.
Optional return type:
The compiler automatically returns the value if the body has a single expression to return the value. We do not need to mention it explicitly.
Curly braces {} are required to indicate that the expression returns a value.
Syntax - Lambda Expressions (Examples)
NO parameter and NO return statement:
() -> {};
//No parameters, with curly parentheses/expression body. No return type.() -> null
NO parameter with return statement:
() -> { return statement; };
//No parameters, with curly parentheses / expression body and return statement.() -> expression
One parameter and NO return statement:
n -> System.out.print(n);
(n) ->{ System.out.print(n) };
(data type n) -> n ;
One parameter with return statement:
n -> {return n;};
or(n) -> {return n;};
n -> expression;
One parameter and return type:
(n) -> {return n;};
orn -> {return n;};
Multiple parameter and NO return statement:
(p, x) -> System.out.println(p + x)
(p, x) ->{ System.out.println(p + x); };
Multiple parameter with return statement:
(p, x) -> { return statement; };
// multiple parameter, with curly parentheses and return statement.(p, x) -> { return (p+x); };
//multiple parameter, with curly parentheses and return statement.
Example 1: Lambda Expression - No Parameter
Create an interface named
Human
and add only one abstract method as shown below. This will be our Functional Interface.
Let’s see how to give an implementation of functional interface using the Lambda Expression. Create a regular class named
MyRunner
.
Run your program. Output:
Hello. It's me again, James
Example 2: Lambda Expressions - One Parameter
Create an interface named
Human
and add only one abstract method as shown below. This will be our Functional Interface.
Let’s see how to give an implementation of functional interface using Lambda expression. Create a regular class named
MyRunner
.
Run your program. Output:
Hello | It’s me Tony
Example 3: Lambda Expressions - One Parameter and Return Type
Create an interface named
Human2
and add only one abstract method as shown below. This will be our Functional Interface.
Let’s see how to give an implementation of function interface using Lambda Expression. Create a regular class named
MyRunner
.
Run your program. Output:
Hello Tony How are you doing
Example 4: Lambda Expression - Multiple Parameters
Create interface named
multipleParameterDemo
and add only one abstract method, As shown below. This will be our Function interface.
Let’s see how to give an implementation of function interface using Lambda expression. Create regular class named
MyRunner
and write below code.
Run your program. Output:
hello | Per Scholas Students
Example 5: Lambda Expressions - Multiple Parameters and a Return Statement
Create interface named
Calculator
and add only one abstract method as shown below. This will be our Function interface.
Let’s see how to give an implementation of function interface using Lambda Expression. Create regular class named
MyRunner2
.
Run your program. Output:
60.0
Topic 4: Built-in Functional Interfaces in Java
Java contains a set of functional interfaces designed for commonly occurring use cases. As such, you do not have to create your own functional interfaces for every little use case.
The following is a list of Java’s most commonly used built-in functional interfaces.
Runnable: contains only the run() method.
Comparable: contains only the compareTo() method.
ActionListener: contains only the actionPerformed() method.
Callable: contains only the call() method.
Predicate: a boolean-valued function that takes an argument and returns true or false.
BiPredicate: a predicate with two arguments.
Consumer: an operation that takes an argument, operates on it, and returns no result.
BiConsumer: a consumer with two arguments.
Supplier: a supplier that returns a value.
Function<T, R>: takes an argument of type T and returns a result of type R.
BiFunction<T, U, R>: takes two arguments of types T and U and returns a result of type R.
Topic 4a: Functional Interface - Consumer<E>
The Java Consumer Interface is a functional interface that represents a function that consumes a value without returning any value. A Java Consumer implementation could be printing out a value or writing it to a file or over the network, etc. Here is an example implementation of the Java Consumer interface:
Syntax:
Consumer<Integer> consumer = (value) -> System.out.println(value);
Example: Create a new class. You can specify any name to the class. Write the code below:
Run your program. Output:
Per Scholas
Topic 4b: Functional Interface - Supplier<E>
The Java Supplier Interface is a functional interface that represents a function that supplies a value of some sorts. The Supplier Interface can also be thought of as a factory interface.
Example: Create a class. You can specify any name to the class, and write code below:
Run your program. Output:
Per Scholas 0.06988892309043637
Topic 4c: Functional Interface - Predicate<E>
The Java Predicate Interface, java.util.function.Predicate
represents a simple function that takes a single value as parameter and returns true or false. Here is how the Functional Interface Predicate looks:
Example: Create a class. You can specify any name to the class, and write the code below:
Output:
Topic 4d: Function interface - Functional<T,R>
The Java Function Interface - Function<T,R> (java.util.function.Function
) is one of the most central functional interfaces in Java. It represents a function (method) that takes a single parameter and returns a single value.
Function Interface - (java.util.function.Function
)
Example: Function Interface - Functional<T,R> Create a class. You can specify any name to the class, and write the code below:
Output:
Knowledge Check
What is Lambda Expression in Java?
What are the benefits of using a Lambda Expression?
What is a Predicate interface?
What is the Consumer interface?
For Further Reading
The content referenced in the following slides will NOT be covered in the scope of this course. However, Per Scholas recommends that you explore the content for upskilling.
Stream API for Function Interface
What is Stream? A stream is a conceptually endless flow of data or elements or a sequence of elements that supports various methods for sequential and parallel aggregate operations.
Overview of Stream API The Java Stream API provides a functional approach to processing collections of objects. The Java Stream API was added in Java 8 along with several other functional programming features. Java 8 provides a new additional package for Stream API: java.util.stream
.
Note: Java InputStream and Java OutputStream of Java IO is for processing streams of objects - not bytes. The InputStream and OutputStream are related to streams of bytes. The Java Stream API is not related to the bytes.
Java Stream forEach() Method
The Java Stream forEach() method is a terminal operation, which starts the internal iteration of the elements in the Stream and applies a Consumer (java.util.function.Consumer
) to each element in the Stream. The forEach() method returns void
. Here is an example of Java Stream forEach().
Output:
Stream API for Function Interface
For more information about Java Streams API, visit the Wiki Document.
Summary
A functional interface has exactly one abstract method and can have any number of default and static methods.
From Java 8 and onwards, Lambda Expressions can be used to represent the instance of a functional interface.
A Lambda Expression is a short block of code, which takes in parameters and returns a value. Lambda expressions are similar to methods, but they do not need a name and they can be implemented right in the body of a method.
References
Last updated