Java Lambda Expressions

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 method add.
  • The lambda expression (int x, int y) -> x + y provides a concise implementation of the add method.
  • The lambda expression is assigned to an instance of the MyAdder interface called adder.
  • 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.