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

  1. What are Java Lambda Expressions?
  2. Syntax of Lambda Expressions
  3. Usage of Lambda Expressions
    • With Collections
    • With Functional Interfaces
  4. Common Practices
    • Filtering Collections
    • Sorting Collections
  5. Best Practices
    • Keep it Simple
    • Use Method References
  6. Conclusion
  7. 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