24
JanLambda Expressions in Java: Explained in Easy Steps
Lambda Expression in Java
A lambda expression in Java is a simple way to write methods in a more compact and readable format. Instead of using lengthy anonymous classes, lambda expressions in Java allow you to pass behavior directly in your code. This makes tasks like iterating through collections easier and keeps your code clean and easy to understand.
In the Java tutorial, let's understand the concept of Lambda Expression in Java, including the Syntax of Lambda Expression in Java, Expression in Java consists of three components, What is Functional Interfaces?, Types of Lambda Expression in Java, and a lot more.
What is Lambda Expression in Java?
A lambda expression in Java is like a shortcut to writing code more efficiently. It lets you define a method or behavior in a simple, compact way without needing to create a whole class. The lambda expression in Java makes your code easier to read and faster to write, especially when working with things like collections or functional programming tasks.
Why Beneficial For You
- Lambda expression in Java allows you to write methods in a shorter, more readable format by eliminating the need for anonymous classes.
- With lambda expression in Java, you can replace bulky anonymous classes with simple one-line methods, making your code cleaner.
- Lambda expression in Java helps in improving the clarity of code, especially when dealing with operations like filtering or sorting.
- It allows you to pass behavior as parameters, making your code more flexible and reusable in different situations.
Syntax of Lambda Expression in Java
2. Basic Syntax
(argument-list) -> {body}
2. Syntax for the Zero Parameter
() -> System.out.println("Zero parameter lambda");
3. Syntax for the One Parameter
(p) -> System.out.println("One parameter: " + p);
4. Syntax for the Multiple Parameter
(p1, p2) -> System.out.println("Multiple parameters: " + p1 + ", " + p2);
Lambda Expression Components
- Argument list: It can be empty or non-empty as well.
- Arrow-token: It is used to link the arguments list and body of expression.
- Body: It contains expressions and statements for lambda expression.
Lambda Expression Functionalities
- Simplifies Code: Lambda expressions let you write simple and clear code without the need for extra classes or methods.
- Enables Inline Behavior: You can define actions directly in your code, making it easier to understand and use without extra steps.
- Supports Functional Interfaces: Lambda expressions work well with functional interfaces (interfaces with just one method), making them ideal for use with collections or streams.
- Enhances Code Flexibility: They allow you to pass code as arguments to methods, which helps in creating more flexible and reusable functions.
What is Functional Interfaces?
A functional interface in Java is an interface with just one abstract method on it. The contract that the lambda expression or method reference will satisfy is defined by this one abstract method. In Java, lambda expressions and method references are used primarily with functional interfaces in mind.
Key points to be remembered for the Functional Interface:
- A functional interface must have only one abstract method. This method is called the functional method.
- Using the @FunctionalInterface annotation is a best practice to ensure the interface has only one abstract method, as it enforces this rule at compile-time.
- A functional interface can have any number of default or static methods as long as it has only one abstract method.
Example: Functional Interface
@FunctionalInterface
interface ScholarHat {
void learn(); // Single abstract method
}
Example: Using Functional Interface in Lambda Expression
@FunctionalInterface
interface ScholarHat {
void study(); // Single abstract method
}
public class LambdaExample {
public static void main(String[] args) {
// Using a lambda expression to implement the ScholarHat interface
ScholarHat learningSession = () -> System.out.println("Studying with ScholarHat!");
learningSession.study(); // Output: Studying with ScholarHat!
}
}
Output
Studying with ScholarHat!
Types of Lambda Expression in Java
1. Lambda Expression in Java with Zero Parameter
A lambda expression with no parameters directly provides an implementation for the functional interface's method.
Example
@FunctionalInterface
interface Greet {
// Single abstract method for the functional interface
void sayHello();
}
public class LambdaExample {
public static void main(String[] args) {
// Lambda expression implementing the sayHello method of the Greet interface
Greet greeting = () -> System.out.println("Hello, World!");
// Calling the sayHello method, which executes the lambda expression
greeting.sayHello();
}
}
Output
Hello, World!
2. Lambda Expression in Java with Single Parameter
A lambda expression with one parameter doesn't need parentheses around the parameter.
Example
@FunctionalInterface
interface Square {
// Single abstract method that takes an integer and returns its square
int calculate(int x);
}
public class LambdaExample {
public static void main(String[] args) {
// Lambda expression implementing the calculate method of the Square interface
Square square = x -> x * x;
// Calling the calculate method with the argument 5, which computes 5 * 5
System.out.println(square.calculate(5));
}
}
Output
25
3. Lambda Expression in Java with Multiple Parameters
A lambda expression with multiple parameters requires parentheses around the parameters.
Example
@FunctionalInterface
interface Add {
// Single abstract method that takes two integers and returns their sum
int sum(int a, int b);
}
public class LambdaExample {
public static void main(String[] args) {
// Lambda expression implementing the sum method of the Add interface
Add addition = (a, b) -> a + b;
// Calling the sum method with arguments 10 and 20, which computes 10 + 20
System.out.println(addition.sum(10, 20));
}
}
Output
30
4. Lambda Expression in Java with Block of Code
A lambda expression with a block of code requires curly braces and a return statement if there is a return value.
Example
@FunctionalInterface
interface Multiply {
// Single abstract method that takes two integers and returns their product
int multiply(int a, int b);
}
public class LambdaExample {
public static void main(String[] args) {
// Lambda expression implementing the multiply method of the Multiply interface
Multiply multiplication = (a, b) -> {
// Calculate the product of a and b
int result = a * b;
// Return the result
return result;
};
// Calling the multiply method with arguments 4 and 5, which computes 4 * 5
System.out.println(multiplication.multiply(4, 5));
}
}
Output
20
5. Lambda Expression in Java with Method Reference
While not a lambda expression per se, method references provide a shorthand way to write lambdas that call a specific method.
Example
@FunctionalInterface
interface Printer {
// Single abstract method that takes a String message and prints it
void print(String message);
}
public class LambdaExample {
public static void main(String[] args) {
// Method reference to System.out.println,
//implementing the print method of the Printer interface
Printer printer = System.out::println;
// Calling the print method with the message "Hello, Method Reference!"
printer.print("Hello, Method Reference!"); // Output: Hello, Method Reference!
}
}
Output
Hello, Method Reference!
Examples of Lambda Expressions in Java
Here are some of the most important examples that will help you to understand Lambda Expression in Java properly:
1. Without Using Lambda Expression
@FunctionalInterface
interface Greet {
void sayHello();
}
public class ScholarHat {
public static void main(String[] args) {
// Implementing the Greet interface using an anonymous class
Greet greeting = new Greet() {
@Override
public void sayHello() {
System.out.println("Hello from ScholarHat!");
}
};
// Calling the sayHello method
greeting.sayHello();
}
}
Output
Hello from ScholarHat!
2. By Using Lambda Expression
@FunctionalInterface
interface Greet {
// Single abstract method to be implemented
void sayHello();
}
public class ScholarHat {
public static void main(String[] args) {
// Implement the Greet interface using a lambda expression
Greet greeting = () -> System.out.println("Hello from ScholarHat!");
// Call the sayHello method of the Greet instance
greeting.sayHello();
}
}
Output
Hello from ScholarHat!
3. Iterating Collections Using the Foreach Loop
In Java, the forEach method of the Collection interface can be used to iterate over collections with the help of lambda expressions. This approach is both concise and readable. Here’s how you can use the forEach method along with lambda expressions to iterate over a collection.
import java.util.Arrays;
import java.util.List;
public class ScholarHat {
public static void main(String[] args) {
// Define a list of strings
List names = Arrays.asList("Aman", "Bhanu", "Charu", "Dev");
// Iterate over the list using forEach and a lambda expression
names.forEach(name -> System.out.println(name));
}
}
Output
Aman
Bhanu
Charu
Dev
Read More: |
for Loop in Java: Its Types and Examples |
while Loop in Java |
do...while Loop in Java - Flowchart & Syntax (With Examples) |
4. Java Lambda Expression With or Without Return Keyword
1. Lambda Expression Without 'return' Keyword
When a lambda expression has a single expression, you can omit the return keyword. This is known as an expression lambda.
@FunctionalInterface
interface Square {
int calculate(int x);
}
public class LambdaExample {
public static void main(String[] args) {
// Lambda expression without return keyword
Square square = x -> x * x;
// Calling the calculate method
System.out.println(square.calculate(5)); // Output: 25
}
}
Output
25
2. Lambda Expression With return Keyword
When a lambda expression contains multiple statements, you need to use curly braces {} and include the return keyword to specify the return value.
@FunctionalInterface
interface Square {
int calculate(int x);
}
public class LambdaExample {
public static void main(String[] args) {
// Lambda expression with return keyword
Square square = x -> {
int result = x * x;
return result;
};
// Calling the calculate method
System.out.println(square.calculate(5));
}
}
Output
25
5. Java Lambda Expression - Creating Thread
Lambda expressions in Java streamline thread creation by directly implementing the Runnable interface, making code more concise and readable. Before Java 8, thread creation required defining a new class or extending the Thread class.
public class LambdaThreadExample {
public static void main(String[] args) {
// Creating a thread using a lambda expression
Thread thread = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("Running in thread: " + Thread.currentThread().getName() + ", Count: " + i);
try {
Thread.sleep(500); // Sleep for 500 milliseconds
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// Start the thread
thread.start();
// Main thread output
for (int i = 0; i < 5; i++) {
System.out.println("Running in main thread: " + Thread.currentThread().getName() + ", Count: " + i);
try {
Thread.sleep(500); // Sleep for 500 milliseconds
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Output
Running in thread: Thread-0, Count: 0
Running in main thread: main, Count: 0
Running in thread: Thread-0, Count: 1
Running in main thread: main, Count: 1
Running in thread: Thread-0, Count: 2
Running in main thread: main, Count: 2
Running in thread: Thread-0, Count: 3
Running in main thread: main, Count: 3
Running in thread: Thread-0, Count: 4
Running in main thread: main, Count: 4
6. Java Lambda Expression - Comparator
Lambda expressions simplify the implementation of the Comparator interface for sorting collections, making the code more concise and readable. Before Java 8, comparators were required to define new classes or anonymous classes.
import java.util.Arrays;
import java.util.List;
public class LambdaComparatorExample {
public static void main(String[] args) {
// Define a list of strings
List names = Arrays.asList("Aman", "Ankita", "Raghav", "Prince");
// Sort the list in natural order using a lambda expression
names.sort((s1, s2) -> s1.compareTo(s2));
// Print the sorted list
System.out.println("Sorted names: " + names);
}
}
Output
Sorted names: [Aman, Ankita, Prince, Raghav]
7. Java Lambda Expression - Filter Collection Data
Lambda expressions in Java can be used to filter data in collections, making it easier to process and manipulate data. The Stream API, introduced in Java 8, provides methods like filters that work seamlessly with lambda expressions for filtering data.
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class LambdaFilterExample {
public static void main(String[] args) {
// Define a list of strings
List names = Arrays.asList("Aman", "Ankita", "Radha", "Price", "Abhishek");
// Filter the list to include only names that start with "A"
List filteredNames = names.stream()
.filter(name -> name.startsWith("A"))
.collect(Collectors.toList());
// Print the filtered list
System.out.println("Filtered names: " + filteredNames);
}
}
Output
Filtered names: [Aman, Ankita, Abhishek]
8. Java Lambda Expression - Event Listener
Lambda expressions in Java can be used to simplify the implementation of event listeners, making your code more concise and readable. This is especially useful in GUI programming with Swing or JavaFX, where event handling is common.
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class LambdaEventListenerSwing {
public static void main(String[] args) {
// Create the JFrame
JFrame frame = new JFrame("Lambda Event Listener Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 200);
// Create a JPanel
JPanel panel = new JPanel();
// Create a JButton
JButton button = new JButton("Click Me!");
// Add ActionListener using lambda expression
button.addActionListener(event -> System.out.println("Button clicked!"));
// Add button to panel
panel.add(button);
// Add panel to frame
frame.add(panel);
// Make the frame visible
frame.setVisible(true);
}
}
Comparing Lambda Expressions with Other Functional Constructs
Lambda Expression in Javaprovides an easy approach to defining single-method interface (or functional interface) instances. However, there are a number of additional functional constructs in Java that have unique uses.
1. Anonymous Classes vs Lambda Expressions
This is thecomparison of Java's anonymous classes and lambda expressions:
Factors | Anonymous Classes | Lambda Expressions |
Syntax | new Interface() { @Override method() { } } | parameters -> expression or parameters -> { statements } |
Use-cases | Implement interfaces or extend classes | Implement functional interfaces (single-method interfaces) |
Readability | More verbose and boilerplate code | More concise and readable |
Constructor Invocation | Can have constructors and instance initializers | It cannot have constructors; only method implementations |
Access to 'this' | Refers to the instance of the anonymous class | Refers to the enclosing class's instance |
Scope | Has its scope; can access enclosing class members | Inherits scope from the enclosing method/class |
Type | Creates a new class at runtime | Directly uses the target functional interface |
When to Use | Use it when you need to extend a class, implement multiple methods, or need more complex logic. | Use for simple implementations of functional interfaces where a single method needs to be implemented. |
Method Access | Can access methods and fields of the enclosing class | Limited to what’s in scope; no direct access to this method. |
2. Lambdas vs Streams API
Factors | Lambda Expression | Streams API |
Purpose | To provide a concise syntax for implementing functional interfaces. | To process sequences of elements (collections) in a declarative way. |
Syntax | parameters -> expression or parameters -> { statements } | collection.stream().operation(...) |
Use Case | Implement functional interfaces such as Runnable, Comparator, etc. | Perform operations on collections like filter, map, reduce, etc. |
Readability | Improves readability by reducing boilerplate code for single-method interfaces. | Improves readability by allowing for a more declarative approach to processing collections. |
Scope | Primarily used within the context of functional interfaces. | Used with collections, arrays, or other data sources that can be converted to a stream. |
Performance | Direct method implementation is generally efficient. | It can be optimized by the JVM andsupports parallel processing for better performance on large datasets. |
State Management | Stateless; each lambda expression typically represents a single, isolated operation. | Stateless by default, but can be stateful in cases like distinct() or sorted(). |
Operations | Limited to the operations defined in the functional interface. | Supports a wide range of operations like filter, map, flatMap, collect, reduce, etc. |
When to Use | Use when you need to implement a functional interface, particularly for short, simple tasks. | Use when you need to process collections in a declarative, functional style, especially with multiple operations or parallel processing. |
3. Lambdas vs Method References
Factors | Lambda Expression | Method Reference |
Purpose | Provides a concise way to implement functional interfaces inline. | A shorthand for calling an existing method in a lambda expression. |
Syntax | parameters -> expression or parameters -> { statements } | ClassName :: methodName or object :: methodName |
Use Case | Used when custom logic needs to be written inline. | Used when an existing method can be referenced directly. |
Readability | More flexible but can be slightly verbose for simple operations. | More concise and readable, especially when referencing simple methods. |
When to use | Use when you need to write inline logic or call methods with parameters. | Use when you are calling an existing method, simplifying the code. |
Flexibility | More flexible; allows writing custom code within the lambda body. | Less flexible; can only be used to reference existing methods. |
Constructor Support | No direct support for constructors; must call them explicitly. | Less flexible; can only be used to reference existing methods. |
Chaining | It can be used in chaining (e.g., in-stream operations). | It can also be used in chaining, often improving readability. |
Performance | Performance is similar to method references but might include extra overhead. | Slightly better performance as it’s a direct method reference. |
Conclusion
In conclusion, we've seen how lambda expressions in Java make working with functional interfaces easier and reduce extra code. They improve code readability, especially when handling collections and tasks like filtering and mapping. Lambda expressions are essential for writing cleaner, more efficient Java code. If you're new to Java, consider joining our Free Java Certification Course for a step-by-step guide to mastering Full Stack Java Development.
Master tech skills for free with our Free Tech Courses—perfect for beginners and experts alike! Advance your career with our Azure AI & ML Certification Training and Azure Cloud DevOps Engineer Certification Training, designed to make you job-ready.
Most Commonly Asked |
HashMap in Java: A Detailed Explanation |
Learn Method Overloading in Java |
How To Reverse A String In Java |
Practice yourself with the following MCQs
Q 1: What is the main advantage of using Lambda expressions in Java?
Explanation: Lambda expressions simplify the syntax of anonymous methods, making the code more concise and easier to read. It allows you to write a method's implementation inline.
Q 2: Which of the following syntax is correct for a Lambda expression in Java?
(int x, int y) -> { return x + y; }
Explanation: The correct syntax for a Lambda expression in Java includes the parameter list in parentheses, followed by the arrow (->) and the method implementation in curly braces.
Q 3: What is the target type of a Lambda expression in Java?
Explanation: Lambda expressions in Java are used to implement functional interfaces. A functional interface is an interface that has only one abstract method.
Q 4: Which of the following is NOT a valid use case for Lambda expressions in Java?
Explanation: Lambda expressions cannot modify the behavior of existing classes. They are primarily used to pass behavior (like methods) as parameters or create implementations of functional interfaces.
Q 5: How can you declare a Lambda expression that takes no arguments and returns a constant value of 5?
()-> 5;
Explanation: The correct syntax for a Lambda expression with no arguments returning a constant value is ()-> 5;
. The empty parentheses represent no arguments, and the value after the arrow is the return value.
FAQs
- No state management (stateless).
- Only works with functional interfaces (one abstract method).
- Limited to simple expressions or blocks of code.
- Difficult to debug due to concise syntax.
- Type inference can be ambiguous in complex cases.