In this article, we’ll look at examples of Javalambda expressions and the use of lambda expressions in function interfaces, generic function interfaces, and flow apis.
Lambda expressions were first introduced in Java8. Its main goal is to improve the expressive ability of language.
Before entering lambdas, however, we first need to understand the functional interface.
What is Functional Interface?
If a Java interface contains one and only one abstract method, it is called a functional interface. Only one method specifies the intended purpose of the interface.
For example, the Runnable interface in the java.lang package; Is a function interface because it constitutes only one method, run ().
Example 1: Defining function interfaces in Java
import java.lang.FunctionalInterface;
@FunctionalInterface
public interface MyInterface{
// the single abstract method
double getValue(a);
}
Copy the code
In the example above, the interface MyInterface has only one abstract method, getValue (). Therefore, it is a functional interface.
Here, we use the annotation @functionInterface. Annotations force the Java compiler to indicate that the interface is a functional interface. Therefore, multiple abstract methods are not allowed. However, this is not mandatory.
In Java7, functional interfaces are treated as a single abstract method or SAM type. SAMs is typically implemented in Java7 using anonymous classes.
Example 2: Implementing 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(); }}Copy the code
Output:
just implemented the Runnable Functional Interface.
Copy the code
Here, we can pass an anonymous class to a method. This helps you write less code in Java7. However, the syntax is still difficult and requires many extra lines of code.
Java8 further extends the capabilities of SAMs. Because we know that the function interface has only one method, we do not need to define the name of the method when passing it as a parameter. Lambda expressions allow us to do this completely.
## Introduction to Lambda expressions Lambda expressions are essentially anonymous or unnamed methods. Lambda expressions do not execute themselves. Instead, it is used to implement methods defined by the function interface.
How do I define lambda expressions in Java?
Here’s how to define lambda expressions in Java.
(parameter list) -> lambda body
Copy the code
The new operator used (->) is called the arrow operator or lambda operator. The syntax may not be clear at present. Let’s explore some examples,
Suppose we have a method like this:
double getPiValue(a) {
return 3.1415;
}
Copy the code
We can write this method using lambda expressions, as follows:
() - >3.1415
Copy the code
Here, the method has no arguments. Therefore, the left side of the operator contains an empty argument. On the right is the lambda body, which specifies the operations of lambda expressions. In this case, it returns the value 3.1415.
The type of the Lambda body
In Java, lambda bodies come in two types.
- A body with a single expression
() -> System.out.println("Lambdas are great");
Copy the code
Lambda bodies of this type are called expression bodies.
- A body consisting of code blocks.
() - > {double pi = 3.1415;
return pi;
};
Copy the code
Lambda bodies of this type are called blocks. A block allows a lambda body to contain multiple statements. These statements are enclosed in braces and must be followed by a semicolon.
Note: For blocks, you can use a return statement if the block returns a value. However, the expression body does not require a return statement.
Example 3: a Lambda expression
Let’s write a Java program that returns the value of Pi using a lambda expression.
As mentioned earlier, lambda expressions do not execute alone. Instead, it forms an implementation of abstract methods defined by the function interface.
Therefore, we need to define a functional interface first.
import java.lang.FunctionalInterface;
// this is functional interface
@FunctionalInterface
interface MyInterface{
// abstract method
double getPiValue(a);
}
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()); }}Copy the code
Output:
Value of Pi = 3.1415
Copy the code
In the example above,
We have created a functional interface called MyInterface. It contains an abstract method called getPiValue ()
In the main class, we declare a reference to MyInterface. Note that we can declare a reference to an interface, but not instantiate it. It is,
// it will throw an error
MyInterface ref = new myInterface();
// it is valid
MyInterface ref;
Copy the code
We then specify a lambda expression for the reference.
ref = () -> 3.1415;
Copy the code
Finally, we call the method getPiValue () using the reference interface
System.out.println("Value of Pi = " + ref.getPiValue());
Copy the code
Lambda expressions with arguments
So far, we have created lambda expressions without any arguments. However, like methods, lambda expressions can have arguments. For example, the book of job Interview and written Test
(n) -> (n%2) = =0
Copy the code
Here, the variable n in parentheses is the argument passed to the lambda expression. The lambda body takes the argument and checks whether it is even or odd.
Example 4: Using a lambda expression with arguments
@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")); }}Copy the code
Output:
Lambda reversed = adbmaL
Copy the code
So far, the function interface we have used accepts only one type of value. For example,
@FunctionalInterface
interface MyInterface {
String reverseString(String n);
}
Copy the code
The function interface above accepts only strings and returns strings. However, we can make the function interface generic to accept any data type. If you are unsure about generics, visit Java generics.
Example 5: Generic function interfaces 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)); }}Copy the code
Output:
Lambda reversed = adbmaL
factorial of 5 = 120
Copy the code
In the example above, we created a generic function interface called GenericInterface. It contains a generic method called func ().
So here, in the main class,
GenericInterface<String>reverse-
Create a reference to the interface. This interface now operates on string data.GenericInterface<Integer>factorial-
Create a reference to the interface. In this case, the interface operates on integer data.
Lambda expressions and the StreamAPI
A new java.util.stream package has been added to JDK8, which allows Java developers to perform collections such as search, filter, map, reduce, or manipulate lists.
For example, we have a data flow (in this case, a list of strings) where each string is a combination of country name and country location. Now, we can process these data streams and retrieve places only from Nepal.
To do this, we can perform batch operations in the stream through a combination of the Stream API and Lambda expressions.
Example 6: Demonstrate 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(a){
// add places and country to the list
places.add("Nepal, Kathmandu");
places.add("Nepal, Pokhara");
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 Nepal:");
// Filter places from Nepal
myPlaces.stream()
.filter((p) -> p.startsWith("Nepal")).map((p) -> p.toUpperCase()) .sorted() .forEach((p) -> System.out.println(p)); }}Copy the code
Output:
Places from Nepal:
NEPAL, KATHMANDU
NEPAL, POKHARA
Copy the code
In the example above, note the following statement:
myPlaces.stream()
.filter((p) -> p.startsWith("Nepal")).map((p) -> p.toUpperCase())
.sorted()
.forEach((p) -> System.out.println(p));
Copy the code
Here, we use the filter (), map (), and forEach () methods of the stream API. These methods can take lambda expressions as input.
We can also define our own expressions based on the syntax we learned above. This enables us to significantly reduce the number of lines of code as we saw in the example above.
Book of Job Interview Written Test