π Introduction to Lambda Expressions in Java
Lambda expressions were introduced in Java 8 as one of the most important features enabling functional programming. They allow you to write concise, clear, and flexible code, especially when using APIs like Streams and functional interfaces.
π Why Were Lambda Expressions Introduced?
Before Java 8, anonymous inner classes were often used to implement instances of functional interfaces (interfaces with a single abstract method). However, they were verbose and cluttered the code. Lambda expressions provide a cleaner and more readable alternative.
π§ What Is a Lambda Expression?
A lambda expression is essentially an anonymous function β a block of code that you can pass around and execute. It can be treated as an object and assigned to variables or passed as parameters.
π Lambda Syntax
(parameters) -> expression
OR
(parameters) -> { statements }
π― Key Features of Lambda Expressions
- Concise code
- No need for anonymous class implementation
- Useful with functional interfaces
- Enhances readability and maintainability
π Functional Interface Requirement
A lambda expression can only be used where a functional interface is expected. A functional interface is an interface that contains exactly one abstract method. Examples include:
Runnable
Callable
Comparator
Consumer
,Function
,Predicate
fromjava.util.function
π‘ Example 1: Simple Lambda with Runnable
public class LambdaRunnable {
public static void main(String[] args) {
Runnable run = () -> System.out.println("Running using lambda!");
run.run();
}
}
π‘ Example 2: Comparator Using Lambda
import java.util.*;
public class LambdaComparator {
public static void main(String[] args) {
List names = Arrays.asList("John", "Alice", "Bob");
Collections.sort(names, (a, b) -> a.compareTo(b));
names.forEach(System.out::println);
}
}
π‘ Example 3: Custom Functional Interface
@FunctionalInterface
interface MathOperation {
int operate(int a, int b);
}
public class LambdaCustom {
public static void main(String[] args) {
MathOperation addition = (a, b) -> a + b;
MathOperation multiply = (a, b) -> a * b;
System.out.println("Addition: " + addition.operate(5, 3));
System.out.println("Multiplication: " + multiply.operate(5, 3));
}
}
π¬ Type Inference in Lambda
Java compiler can infer types from the context:
(a, b) -> a + b
instead of (int a, int b) -> a + b
π§ͺ Lambda with Java Collections
List<String> items = Arrays.asList("Apple", "Banana", "Cherry");
items.forEach(item -> System.out.println(item));
π Lambda with Streams
import java.util.*;
import java.util.stream.*;
public class StreamLambda {
public static void main(String[] args) {
List numbers = Arrays.asList(10, 20, 30, 40);
int sum = numbers.stream()
.filter(n -> n > 15)
.mapToInt(n -> n)
.sum();
System.out.println("Sum of numbers > 15: " + sum);
}
}
β οΈ Common Mistakes
- Using lambda for non-functional interfaces
- Overcomplicating logic inside lambda
- Not understanding scope and final/effectively final rules
π Variable Scope in Lambda
Variables used in a lambda must be effectively final. Example:
int factor = 2;
List<Integer> list = Arrays.asList(1, 2, 3);
list.forEach(n -> System.out.println(n * factor));
π Lambda with java.util.function Package
Java 8 introduced a set of functional interfaces in the java.util.function
package:
- Predicate<T>: boolean-valued function
- Function<T, R>: Accepts T and returns R
- Consumer<T>: Accepts T and returns void
- Supplier<T>: Returns T and takes nothing
π‘ Real-World Use Case
import java.util.function.Predicate;
import java.util.*;
public class FilterExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Adam", "Alex", "Brian", "Bob");
Predicate<String> startsWithA = name -> name.startsWith("A");
names.stream()
.filter(startsWithA)
.forEach(System.out::println);
}
}
π§΅ Method References and Lambdas
You can simplify lambdas further using method references:
list.forEach(System.out::println);
is equivalent to
list.forEach(item -> System.out.println(item));
βοΈ How to Compile and Run Lambda Code
- Use Java 8 or later.
- Save code in a file named
Example.java
. - Compile with
javac Example.java
. - Run using
java Example
.
π§Ύ Conclusion
Lambda expressions revolutionized Java programming by bringing functional-style syntax to an object-oriented language. They enable more readable and maintainable code, especially when dealing with collection operations and APIs that expect functional interfaces.
By mastering lambda expressions, developers can write cleaner code, reduce boilerplate, and embrace modern programming paradigms such as streams and reactive programming. Lambda is not just a featureβit is a gateway to writing expressive, flexible, and efficient Java applications.