In this article, we will learn about Java lambda expression and the use of lambda expression with functional interfaces, generic functional interface, and stream API with the help of examples.
The lambda expression was presented first time in Java 8. Its primary objective to expand the expressive intensity of the language.
Be that as it may, prior to getting into lambdas, we first need to comprehend functional interfaces.
In this article, you will learn-
What is Functional Interface?
If a Java interface contains one and only one abstract technique, at that point it is named as functional interface. This just a single strategy indicates the expected purpose of the interface.
For instance, the Runnable interface from package java. lang; is a functional interface since it constitutes just a single technique for example run().
Example 1: Define a Functional Interface in java
import java.lang.FunctionalInterface;
@FunctionalInterface
public interface MyInterface{
// the single abstract method
double getValue();
}
In the above example, the interface MyInterface has just one abstract technique getValue(). Consequently, it is a functional interface.
Here, we have used the comment @FunctionalInterface. The annotation forces the Java compiler to demonstrate that the interface is a functional interface. Consequently, doesn’t allow to have more than one abstract technique. Be that as it may, it isn’t obligatory however.
In Java 7, functional interfaces were considered as Single Abstract Methods or SAM type. SAMs were usually actualized with Anonymous Classes in Java 7.
Example 2: Implement SAM with anonymous classes in java
public class FunctionInterfaceTest {
public static void main(String[] args) {
// anonymous class
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("I just implemented the Runnable Functional Interface.");
}
}).start();
}
}
Output
I just implemented the Runnable Functional Interface.
Here, we can handle an unknown class to a strategy. This helps with writing programs with less codes in Java 7. However, the punctuation was as yet troublesome and a lot of extra lines of code were required.
Java 8 expanded the intensity of a SAMs by going above and beyond. Since we realize that a practical interface has only one strategy, there should be no compelling reason to characterize the name of that technique when passing it as a contention. Lambda articulation permits us to do precisely that.
Introduction to lambda expressions
Lambda expression is, basically, a mysterious or anonymous strategy. The lambda expression doesn’t execute its own. it is used to execute a technique characterized by a functional interface.
How to characterize lambda expression in Java?
Here are the means by which we can characterize lambda expression in Java.
(parameter list) -> lambda body
The new operator (- >) used is known as a bolt operator or a lambda operator. The syntax probably won’t be clear right now. We should investigate a few examples,
Assume, we have a strategy like this:
double getPiValue() {
return 3.1415;
}
We can write this method using lambda expression as:
() -> 3.1415
Here, the method doesn’t have any parameters. Thus, the left half of the operator incorporates an unfilled parameter. The correct side is the lambda body that indicates the activity of the lambda articulation. For this situation, it restores the worth 3.1415.
Types of Lambda Body
In Java, the lambda body is of two types.
- A body with a single expression
() -> System.out.println("Lambdas are great");
This type of lambda body is known as the expression body.
- A body that consists of a block of code.
() -> {
double pi = 3.1415;
return pi;
};
This sort of lambda body is known as a square body. The block body allows the lambda body to incorporate different statements. These statements are encased inside the supports and you need to add a semi-colon after the braces.
Note: For the square body, you can have a return statement if the body returns worth it. In any case, the expression body doesn’t need a bring explanation back.
Example 3: Lambda Expression
Let’s write a Java program that returns the value of Pi using the lambda expression.
As referenced before, a lambda expression isn’t executed on its own. Or maybe, it shapes the usage of the theoretical strategy characterized by the functional interface.
In this way, we need to characterize a functional interface first.
import java.lang.FunctionalInterface;
// this is functional interface
@FunctionalInterface
interface MyInterface{
// abstract method
double getPiValue();
}
public class Main {
public static void main( String[] args ) {
// declare a reference to MyInterface
MyInterface ref;
// lambda expression
ref = () -> 3.1415;
System.out.println("Value of Pi = " + ref.getPiValue());
}
}
Output
Value of Pi = 3.1415
In the above example,
We have made a functional interface named MyInterface. It contains a single abstract strategy named getPiValue()
Inside the Main class, we have pronounced a reference to MyInterface. Note that we can proclaim a reference of an interface however we can’t start up an interface. That is,
// it will throw an error
MyInterface ref = new myInterface();
// it is valid
MyInterface ref;
We then assigned a lambda expression to the reference.
ref = () -> 3.1415;
Finally, we call the method getPiValue() using the reference interface. When
System.out.println("Value of Pi = " + ref.getPiValue());
Lambda Expressions with parameters
Till now we have made lambda expressions with no parameters. However, like strategies, lambda expressions can likewise have parameters. For instance,
(n) -> (n%2)==0
Here, the variable n inside the enclosure is a parameter passed to the lambda expression. The lambda body takes the parameter and checks if it is even or odd.
Example 4: Using lambda expression with parameters
@FunctionalInterface
interface MyInterface {
// abstract method
String reverse(String n);
}
public class Main {
public static void main( String[] args ) {
// declare a reference to MyInterface
// assign a lambda expression to the reference
MyInterface ref = (str) -> {
String result = "";
for (int i = str.length()-1; i >= 0 ; i--)
result += str.charAt(i);
return result;
};
// call the method of the interface
System.out.println("Lambda reversed = " + ref.reverse("Lambda"));
}
}
Output
Lambda reversed = adbmaL
Generic Functional Interface
Till now we have used the functional interface that accepts just one kind of significant worth. For instance,
@FunctionalInterface
interface MyInterface {
String reverseString(String n);
}
The above functional interface just accepts String and brings String back. However, we can make the functional interface generic, so any data type is accepted. If you don’t know about java generics,
Example 5: Generic Functional Interface and Lambda Expressions
// GenericInterface.java
@FunctionalInterface
interface GenericInterface<T> {
// generic method
T func(T t);
}
// GenericLambda.java
public class Main {
public static void main( String[] args ) {
// declare a reference to GenericInterface
// the GenericInterface operates on String data
// assign a lambda expression to it
GenericInterface<String> reverse = (str) -> {
String result = "";
for (int i = str.length()-1; i >= 0 ; i--)
result += str.charAt(i);
return result;
};
System.out.println("Lambda reversed = " + reverse.func("Lambda"));
// declare another reference to GenericInterface
// the GenericInterface operates on Integer data
// assign a lambda expression to it
GenericInterface<Integer> factorial = (n) -> {
int result = 1;
for (int i = 1; i <= n; i++)
result = i * result;
return result;
};
System.out.println("factorial of 5 = " + factorial.func(5));
}
}
Output
Lambda reversed = adbmaL
factorial of 5 = 120
In the above example, we have made a generic functional interface named GenericInterface. It contains a generic strategy named func().
- Here, inside the Main class, GenericInterface reverse – creates a reference to the interface. The interface now operates on String type of data.
- GenericInterface factorial – creates a reference to the interface. The interface, in this case, operates on the Integer type of data.
Lambda Expression and Stream API
The new java. util. stream package has been added to JDK8 which allows java developers to perform activities like search, filter, map, reduce, or control assortments like Lists.
For instance, we have a stream of data (for our situation a List of String) where each string is a mix of country name and spot of the country. Presently, we can deal with this stream of data and recover just the spots from Pakistan.
For this, we can perform activities in the stream by the mix of Stream API and Lambda expression.
Example 6: Demonstration of using lambdas with the Stream API
import java.util.ArrayList;
import java.util.List;
public class StreamMain {
// create an object of list using ArrayList
static List<String> places = new ArrayList<>();
// preparing our data
public static List getPlaces(){
// add places and country to the list
places.add("Pakistan, Islamabad");
places.add("Pakistan, Peshawar");
places.add("India, Delhi");
places.add("USA, New York");
places.add("Africa, Nigeria");
return places;
}
public static void main( String[] args ) {
List<String> myPlaces = getPlaces();
System.out.println("Places from Pakistan:");
// Filter places from Pakistan
myPlaces.stream()
.filter((p) -> p.startsWith("pakistan"))
.map((p) -> p.toUpperCase())
.sorted()
.forEach((p) -> System.out.println(p));
}
}
Output
Places from pakistan:
PAKISTAN, Isamabad
Pakistan, Peshawar
In the above example, notice the statement,
myPlaces.stream()
.filter((p) -> p.startsWith("Pakistan"))
.map((p) -> p.toUpperCase())
.sorted()
.forEach((p) -> System.out.println(p));
Here, we are using the strategies like filter(), map() and forEach() of the Stream API. These strategies can accept a lambda expression as input.
We can likewise characterize our own appearances dependent on the syntax we learned previously. This allows us to decrease the lines of code radically as we found in the above example.
Thanks for reading! We hope you found this tutorial helpful and we would love to hear your feedback in the Comments section below. And show us what you’ve learned by sharing your photos and creative projects with us.