Lambda expressions, introduced in Java 8, are a powerful feature that allows you to write concise and functional code. They enable you to treat functionality as a method argument or to create small function implementations. This section will cover the basics of lambda expressions, their syntax, and practical examples to help you understand and use them effectively.

Key Concepts

  1. Functional Interface: An interface with a single abstract method. Lambda expressions can be used to instantiate these interfaces.
  2. Syntax: The structure of a lambda expression.
  3. Usage: Common scenarios where lambda expressions are useful.

Functional Interface

A functional interface is an interface with only one abstract method. Java provides several built-in functional interfaces in the java.util.function package, such as Predicate, Function, Supplier, and Consumer.

Example of a Functional Interface

@FunctionalInterface
interface MyFunctionalInterface {
    void myMethod();
}

Syntax of Lambda Expressions

The syntax of a lambda expression consists of three parts:

  1. Parameter List: Enclosed in parentheses, similar to method parameters.
  2. Arrow Token: -> separates the parameter list from the body.
  3. Body: Contains the code to be executed, which can be a single expression or a block of statements.

Basic Syntax

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

Examples

  1. No Parameters
() -> System.out.println("Hello, World!");
  1. Single Parameter
x -> x * x
  1. Multiple Parameters
(x, y) -> x + y

Practical Examples

Example 1: Using Lambda with Runnable

public class LambdaExample {
    public static void main(String[] args) {
        // Traditional way using an anonymous class
        Runnable runnable1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("Runnable using anonymous class");
            }
        };

        // Using lambda expression
        Runnable runnable2 = () -> System.out.println("Runnable using lambda expression");

        // Execute both runnables
        runnable1.run();
        runnable2.run();
    }
}

Example 2: Using Lambda with Comparator

import java.util.Arrays;
import java.util.Comparator;

public class LambdaComparatorExample {
    public static void main(String[] args) {
        String[] names = {"John", "Alice", "Bob"};

        // Traditional way using an anonymous class
        Arrays.sort(names, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return s1.compareTo(s2);
            }
        });

        // Using lambda expression
        Arrays.sort(names, (s1, s2) -> s1.compareTo(s2));

        // Print sorted names
        for (String name : names) {
            System.out.println(name);
        }
    }
}

Exercises

Exercise 1: Simple Lambda Expression

Write a lambda expression that takes two integers and returns their sum.

Solution:

public class LambdaExercise1 {
    public static void main(String[] args) {
        // Lambda expression to add two integers
        Sum sum = (a, b) -> a + b;

        // Test the lambda expression
        System.out.println("Sum: " + sum.add(5, 3)); // Output: Sum: 8
    }

    @FunctionalInterface
    interface Sum {
        int add(int a, int b);
    }
}

Exercise 2: Using Lambda with List

Write a lambda expression to filter a list of integers and print only the even numbers.

Solution:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class LambdaExercise2 {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        // Filter even numbers using lambda expression
        List<Integer> evenNumbers = numbers.stream()
                                           .filter(n -> n % 2 == 0)
                                           .collect(Collectors.toList());

        // Print even numbers
        evenNumbers.forEach(System.out::println);
    }
}

Common Mistakes and Tips

  1. Type Inference: Java can often infer the types of parameters, so you don't need to specify them explicitly.
  2. Single Statement: If the body contains a single statement, you can omit the curly braces and the return keyword.
  3. Functional Interface: Ensure the interface you are using has only one abstract method; otherwise, it cannot be used with lambda expressions.

Conclusion

Lambda expressions simplify the syntax and make your code more readable and concise. They are particularly useful in functional programming and when working with collections. Understanding and using lambda expressions will significantly enhance your Java programming skills. In the next section, we will explore more advanced topics in object-oriented programming, such as interfaces and abstract classes.

Java Programming Course

Module 1: Introduction to Java

Module 2: Control Flow

Module 3: Object-Oriented Programming

Module 4: Advanced Object-Oriented Programming

Module 5: Data Structures and Collections

Module 6: Exception Handling

Module 7: File I/O

Module 8: Multithreading and Concurrency

Module 9: Networking

Module 10: Advanced Topics

Module 11: Java Frameworks and Libraries

Module 12: Building Real-World Applications

© Copyright 2024. All rights reserved