Java Lambda Expressions: A Beginner’s Tutorial
In the world of Java programming, Lambda expressions have emerged as a powerful and concise way to represent anonymous functions. Introduced in Java 8, Lambda expressions provide a more compact and readable syntax for implementing functional interfaces. They are particularly useful when working with collections, stream API, and multi - threading. This tutorial aims to introduce beginners to the fundamental concepts of Java Lambda expressions, show how to use them, and share common practices and best practices.
Table of Contents
- What are Java Lambda Expressions?
- Syntax of Lambda Expressions
- Usage of Lambda Expressions
- With Collections
- With Functional Interfaces
- Common Practices
- Filtering Collections
- Sorting Collections
- Best Practices
- Keep it Simple
- Use Method References
- Conclusion
- References
What are Java Lambda Expressions?
A Java Lambda expression is a short block of code that takes in parameters and returns a value. Lambda expressions are similar to methods, but they do not need a name and can be implemented right in the body of a method. They are mainly used to implement functional interfaces, which are interfaces that have exactly one abstract method.
Syntax of Lambda Expressions
The general syntax of a Lambda expression is as follows:
(parameter_list) -> { method_body }
parameter_list: This is the list of parameters that the Lambda expression takes. It can be empty, have one parameter, or multiple parameters.->: This is the arrow token, which separates the parameter list from the method body.method_body: This is the code that the Lambda expression executes. It can be a single statement or a block of statements.
Here is a simple example of a Lambda expression that takes two integers and returns their sum:
(int a, int b) -> { return a + b; }
If the method body contains only one statement, you can omit the curly braces and the return keyword:
(int a, int b) -> a + b
If the parameter types can be inferred from the context, you can also omit them:
(a, b) -> a + b
Usage of Lambda Expressions
With Collections
One of the most common use cases of Lambda expressions is working with collections. Java 8 introduced the forEach method in the Iterable interface, which allows you to iterate over a collection using a Lambda expression.
import java.util.ArrayList;
import java.util.List;
public class CollectionLambdaExample {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("Alice");
names.add("Bob");
names.add("Charlie");
// Using Lambda expression with forEach
names.forEach(name -> System.out.println(name));
}
}
With Functional Interfaces
Lambda expressions are used to implement functional interfaces. For example, the Runnable interface is a functional interface with a single abstract method run(). You can use a Lambda expression to create an instance of Runnable.
public class RunnableLambdaExample {
public static void main(String[] args) {
// Using Lambda expression to implement Runnable
Runnable task = () -> {
for (int i = 0; i < 5; i++) {
System.out.println("Task is running: " + i);
}
};
Thread thread = new Thread(task);
thread.start();
}
}
Common Practices
Filtering Collections
You can use Lambda expressions with the Stream API to filter collections. The filter method in the Stream API takes a Predicate functional interface, which can be implemented using a Lambda expression.
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class FilteringExample {
public static void main(String[] args) {
List<Integer> numbers = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
numbers.add(i);
}
// Filter even numbers
List<Integer> evenNumbers = numbers.stream()
.filter(num -> num % 2 == 0)
.collect(Collectors.toList());
System.out.println(evenNumbers);
}
}
Sorting Collections
You can use Lambda expressions to define custom sorting logic for collections. The sort method in the List interface takes a Comparator functional interface, which can be implemented using a Lambda expression.
import java.util.ArrayList;
import java.util.List;
public class SortingExample {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("Charlie");
names.add("Alice");
names.add("Bob");
// Sort names in ascending order
names.sort((name1, name2) -> name1.compareTo(name2));
System.out.println(names);
}
}
Best Practices
Keep it Simple
Lambda expressions are meant to be short and concise. Avoid writing long and complex Lambda expressions. If your Lambda expression becomes too long, consider refactoring it into a separate method and using method references.
Use Method References
Method references are a more concise way to write Lambda expressions when the Lambda expression simply calls an existing method. For example, instead of using a Lambda expression to call the System.out::println method, you can use a method reference.
import java.util.ArrayList;
import java.util.List;
public class MethodReferenceExample {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("Alice");
names.add("Bob");
names.add("Charlie");
// Using method reference with forEach
names.forEach(System.out::println);
}
}
Conclusion
Java Lambda expressions are a powerful addition to the Java programming language. They provide a more concise and readable way to implement functional interfaces, especially when working with collections and the Stream API. By understanding the fundamental concepts, syntax, and common practices of Lambda expressions, beginners can start using them effectively in their Java programs. Remember to follow the best practices to keep your code clean and maintainable.
References
- Oracle Java Documentation: https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html
- Baeldung: https://www.baeldung.com/java-8-lambda-expressions-tips