Prerequisites:
Introduction to Java lambdas
Lambda expressions in Java are used to provide a concise way to implement functional interfaces, which are interfaces with a single abstract method. These interfaces are also known as functional interfaces or SAM (Single Abstract Method) interfaces.
The basic structure of a Lambda expression is:
(parameters) -> expression
or
(parameters) -> { statements; }
Now, let’s break down each part:
1. Parameters:
- Enclosed in parentheses
()
. - Represents the input parameters for the lambda expression.
- If there are no parameters, empty parentheses are used.
(int x, int y) -> // Rest of the lambda expression
2. Arrow (->
):
- Separates the parameter list from the body.
- Indicates that the parameters are going to the body of the lambda expression.
(int x, int y) -> // Rest of the lambda expression
3. Body:
- Contains the code or expressions that make up the functionality of the lambda expression.
- If the body consists of a single expression, the return type and the return keyword are implicit.
- If the body contains multiple statements, it is enclosed in curly braces
{ }
.
(int x, int y) -> x + y
or
(int x, int y) -> {
// statements
return x + y;
}
Here are a few more examples for better understanding:
Lambda with no parameters:
() -> System.out.println("Hello, Lambda!");
Lambda with a single parameter:
(String message) -> System.out.println(message);
Lambda with multiple parameters:
(int x, int y) -> x + y;
Lambda with a block body:
(int x, int y) -> {
int sum = x + y;
return sum;
}
Example Of Lambda Expression
Here’s a simple example of a lambda expression in Java:
// Functional Interface
@FunctionalInterface
interface MyAdder {
int add(int a, int b);
}
public class LambdaExample {
public static void main(String[] args) {
// Using a lambda expression to implement the add method
MyAdder adder = (int x, int y) -> x + y;
// Calling the add method using the lambda expression
int result = adder.add(5, 3);
// Printing the result
System.out.println("Result: " + result);
}
}
In this example:
MyAdder
is a functional interface with a single abstract methodadd
.- The lambda expression
(int x, int y) -> x + y
provides a concise implementation of theadd
method. - The lambda expression is assigned to an instance of the
MyAdder
interface calledadder
. - The
adder.add(5, 3)
call uses the lambda expression to add two numbers. - The result is printed, and the output should be:
Result: 8
.
How to pass Lambda expression as parameter ?
you can pass lambda expressions as parameters to methods by using functional interfaces. They can be used as the parameter types for methods accepting lambda expressions. Here’s a step-by-step guide:
1. Define a Functional Interface:
Create a functional interface with a single abstract method that matches the signature of the lambda expression you want to pass.
@FunctionalInterface
interface MyFunction {
void myMethod(String s);
}
2. Create a method that Accepts the Functional Interface:
Create a method that takes an instance of the functional interface as a parameter.
public class LambdaExample {
public static void performOperation(MyFunction function, String input) {
function.myMethod(input);
}
public static void main(String[] args) {
// Call the method and pass a lambda expression
performOperation((s) -> System.out.println("Hello, " + s), "World");
}
}
3. Pass a Lambda Expression:
When calling the method, pass a lambda expression that matches the method’s functional interface parameter.
performOperation((s) -> System.out.println("Hello, " + s), "World");
In this example, the lambda expression (s) -> System.out.println("Hello, " + s)
is passed to the performOperation
method. The method then calls the lambda expression, effectively executing the code specified in the lambda.
This approach allows you to pass different behaviors (expressed as lambda expressions) to a method,
Use cases of Lambda expressions
1. List Iteration using forEach:
Lambda expressions make it easy to iterate over collections using the forEach
method.
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(name -> System.out.println("Hello, " + name));
2. Runnable Interface for Multithreading:
Lambda expressions simplify the creation of threads using the Runnable
interface.
Runnable myRunnable = () -> System.out.println("Running...");
Thread thread = new Thread(myRunnable);
thread.start();
3. Comparator for Sorting:
Lambda expressions are commonly used for defining custom sorting logic using the Comparator
interface.
List<String> fruits = Arrays.asList("Apple", "Banana", "Orange");
fruits.sort((s1, s2) -> s1.compareToIgnoreCase(s2));
4. Stream API for Data Processing:
Lambda expressions work seamlessly with the Stream API, enabling concise and functional-style data processing.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream().mapToInt(i -> i).sum();
5. Filtering Collections:
Lambda expressions can be used to filter elements in a collection based on a condition.
List<Integer> evenNumbers = numbers.stream().filter(n -> n % 2 == 0).collect(Collectors.toList());
Lambda expressions are particularly beneficial when working with functional interfaces, collections, and scenarios that involve passing behavior as an argument.