Unlocking Java’s Potential: A Journey into Lambda Expressions

Ayon Das
4 min readMay 5, 2024
Unlocking Java’s Potential: A Journey into Lambda Expressions

Introduction: Lambda expressions in Java are a powerful feature introduced in Java 8 that allows you to treat functionality as a method argument or to create anonymous functions. They provide a concise way to express instances of single-method interfaces (often referred to as functional interfaces), which enables you to write more readable and maintainable code, especially when working with collections and streams.

The basic syntax of a lambda expression consists of the following parts:

Before writing a lambda expression we need to know about the method present in the functional interface. These interfaces are annotated with @FunctionalInterface.For example :

@FunctionalInterface
interface MyInterface {
void myMethod(int x);
}

Syntax of lambda expressions to create an instance of an anonymous class that implements the above functional interface.

(parameters) -> expression
(parameters) -> { statements; }

Parameters: These are method parameters of the function present in the functional interface. The parameter list can be empty or non-empty. If there’s only one parameter, you can omit the parentheses. If there are no parameters, you still need empty parentheses ().

Arrow ->: This separates the parameter list from the body of the lambda expression.

Body: This can be a single expression without curly braces or a block of statements enclosed in curly braces.

Here’s a simple example to demonstrate the usage of lambda expressions using the above functional interface:

// Functional interface
interface MyInterface {
void myMethod(int x);
}

public class Main {
public static void main(String[] args) {
// Using lambda expression to implement MyInterface
MyInterface obj = (int x) -> System.out.println(x * x);
obj.myMethod(5); // Output: 25
}
}

Benefits of lambda expressions:

  1. Conciseness: Lambda expressions enable more concise code compared to anonymous classes.
  2. Readability: They improve readability by reducing boilerplate code, especially when working with collections and streams.
  3. Flexibility: Lambda expressions provide flexibility in passing behavior as an argument to a method.
  4. Lambda expressions are commonly used with the Streams API to perform operations on collections.

While lambda expressions are powerful, they have some limitations:

Access to Local Variables: Lambda expressions can access local variables of the enclosing scope, but these variables must be effectively final (i.e., their values must not change after they are initialized).

Now let’s delve into how a lambda expression works internally with a functional interface in Java.

First, let’s define a simple functional interface:

@FunctionalInterface
interface Calculator {
int calculate(int x, int y);
}

Now, let’s use a lambda expression to implement this interface:

public class Main {
public static void main(String[] args) {
Calculator add = (int x, int y) -> x + y;
System.out.println("Addition: " + add.calculate(5, 3)); // Output: Addition: 8

Calculator subtract = (int x, int y) -> x - y;
System.out.println("Subtraction: " + subtract.calculate(5, 3)); // Output: Subtraction: 2
}
}

(or) without data types in method parameters. With the instance type “Calculator”, the compiler knows that it is a functional interface and it can have only one method and the parameter signature of the method is (int,int) and the return type of the method is also int. Note, if you are using curly braces then you have to write the “return” keyword to return the value from the method.

public class Main {
public static void main(String[] args) {
Calculator add = (x,y) -> x + y;
System.out.println("Addition: " + add.calculate(5, 3)); // Output: Addition: 8

Calculator subtract = (x,y) -> x - y;
System.out.println("Subtraction: " + subtract.calculate(5, 3)); // Output: Subtraction: 2
}
}

Internal mechanism explanation: When you compile the code containing lambda expressions, the Java compiler does similar work like implementing a method in an anonymous class, but with a slight difference:

  1. Functional Interface Instance Creation: The lambda expression (int x, int y) -> x + y or (int x, int y) -> x - y is converted into an instance of Calculator.
  2. Method Implementation: The lambda expression corresponds to the calculate(int x, int y) method of the Calculator interface. Internally, the lambda expression becomes the implementation of the calculate(int x, int y) method.
  3. Behind the Scenes: Java creates an anonymous class that implements the Calculator interface. Inside this anonymous class, it implements the calculate(int x, int y) method with the code provided in the lambda expression.

Now, here below is the program without lambda expression:

Calculator add = new Calculator() {
@Override
public int calculate(int x, int y) {
return x + y;
}
};

Calculator subtract = new Calculator() {
@Override
public int calculate(int x, int y) {
return x - y;
}
};

Understanding lambda expressions is crucial for modern Java development, as they greatly enhance the expressiveness and flexibility of the language.

--

--

Ayon Das

👋 Hello! I'm a passionate software developer proficient in Java, Spring Boot, and microservices. Continuous learning and knowledge sharing fuel my enthusiasm.