Java · Collections · Topic 9
Lambda Expressions
Write concise behavior with lambdas, functional interfaces, built-in functions, method references, and safe variable capture.
Step 1 of 19
9.1 Introduction
Define lambda expressions and recognize their principal Java uses.
A lambda expression is a short way to represent a block of code that can be passed to a method. It has no method name, may accept parameters, and may return a value.
Common uses
- Functional interfaces
- Collections
- Streams API
- Event handling
- Multithreading
Check your understanding: In which Java version were lambda expressions introduced?
Java 8.
Step 2 of 19
9.2 Basic Syntax
Read the parameter list, arrow, and body of a lambda.
(parameters) -> expression
(parameters) -> {
statements;
}
(a, b) -> a + bCheck your understanding: What does (a,b) -> a+b return?
The sum of a and b.
Step 3 of 19
9.3 Lambda Expression Forms
Write lambdas with zero, one, or multiple parameters and expression or block bodies.
| Form | Example |
|---|---|
| No parameter | () -> System.out.println("Hello Java") |
| One parameter | name -> System.out.println(name) |
| Multiple parameters | (a, b) -> a + b |
| Explicit types | (int a, int b) -> a + b |
| Statement block | (a, b) -> { int result=a+b; return result; } |
Check your understanding: When braces surround multiple value-returning statements, what keyword is required?
return.
Step 4 of 19
9.4 Functional Interface
Connect a lambda to an interface containing one abstract method.
@FunctionalInterface
interface Greeting {
void sayHello();
}
public class FunctionalInterfaceDemo {
public static void main(String[] args) {
Greeting greeting = () -> System.out.println("Hello Java");
greeting.sayHello();
}
}Hello JavaCheck your understanding: How many abstract methods does a functional interface contain?
Exactly one.
Step 5 of 19
9.5 @FunctionalInterface Annotation
Use the annotation to make functional-interface intent compiler-checked.
@FunctionalInterface
interface Calculator {
int calculate(int a, int b);
default void describe() { System.out.println("Calculator"); }
}Allowed members
- One abstract method
- Any number of default methods
- Any number of static methods
- Methods inherited from Object
Check your understanding: May a functional interface contain default and static methods?
Yes, in any number.
Step 6 of 19
9.6 Lambda with Parameters and Return Value
Implement multiple calculations through one functional interface.
@FunctionalInterface
interface Calculator {
int calculate(int a, int b);
}
public class LambdaDemo {
public static void main(String[] args) {
Calculator addition = (a, b) -> a + b;
Calculator subtraction = (a, b) -> a - b;
Calculator multiplication = (a, b) -> a * b;
System.out.println("Result: " + addition.calculate(10, 20));
System.out.println("Subtract: " + subtraction.calculate(10, 5));
System.out.println("Multiply: " + multiplication.calculate(10, 5));
}
}Result: 30
Subtract: 5
Multiply: 50Check your understanding: What result does addition.calculate(10,20) produce?
30.
Step 7 of 19
9.7 Lambda versus Anonymous Class
Replace a single-method anonymous implementation with a lambda.
Runnable verbose = new Runnable() {
public void run() { System.out.println("Task is running"); }
};
Runnable concise = () -> System.out.println("Task is running");Check your understanding: Which version is normally shorter for Runnable?
The lambda version.
Step 8 of 19
9.8 Lambda with Collections
Process each collection element with forEach().
import java.util.Arrays;
import java.util.List;
public class LambdaCollectionDemo {
public static void main(String[] args) {
List<String> names = Arrays.asList("Amit", "Neha", "Raj");
names.forEach(name -> System.out.println(name));
}
}Amit
Neha
RajCheck your understanding: Which method reference is equivalent to name -> System.out.println(name)?
System.out::println.
Step 9 of 19
9.9 Sorting Using Lambda
Supply ascending, descending, and length comparators as lambdas.
import java.util.*;
public class LambdaSortDemo {
public static void main(String[] args) {
List<String> names = new ArrayList<>(Arrays.asList("Raj", "Amit", "Neha"));
names.sort((first, second) -> first.compareTo(second));
System.out.println(names);
names.sort((first, second) -> second.compareTo(first));
System.out.println(names);
names.sort((first, second) -> Integer.compare(first.length(), second.length()));
System.out.println(names);
}
}[Amit, Neha, Raj]
[Raj, Neha, Amit]
[Raj, Neha, Amit]Check your understanding: How can strings be sorted by length?
Compare first.length() and second.length(), preferably with Integer.compare.
Step 10 of 19
9.10 Built-in Functional Interfaces
Identify Java’s core java.util.function interfaces.
| Interface | Role |
|---|---|
| Predicate<T> | Tests a value |
| Function<T,R> | Transforms a value |
| Consumer<T> | Performs an action |
| Supplier<T> | Provides a value |
Check your understanding: Which package contains these interfaces?
java.util.function.
Step 11 of 19
9.11 Predicate<T>
Test a value and obtain a boolean result.
import java.util.function.Predicate;
public class PredicateDemo {
public static void main(String[] args) {
Predicate<Integer> isEven = number -> number % 2 == 0;
System.out.println(isEven.test(10));
System.out.println(isEven.test(15));
}
}true
falseCommon uses
- Filtering
- Testing conditions
- Validation
Check your understanding: What does isEven.test(15) return?
false.
Step 12 of 19
9.12 Combining Predicates
Compose conditions with and(), or(), and negate().
import java.util.function.Predicate;
public class PredicateCombinationDemo {
public static void main(String[] args) {
Predicate<Integer> greaterThan10 = number -> number > 10;
Predicate<Integer> lessThan50 = number -> number < 50;
Predicate<Integer> condition = greaterThan10.and(lessThan50);
System.out.println(condition.test(25));
System.out.println(condition.negate().test(25));
}
}true
falseCheck your understanding: Does greaterThan10.and(lessThan50).test(25) return true?
Yes.
Step 13 of 19
9.13 Function<T, R>
Transform an input of type T into a result of type R.
import java.util.function.Function;
public class FunctionDemo {
public static void main(String[] args) {
Function<String, Integer> length = text -> text.length();
Function<Integer, Integer> square = number -> number * number;
System.out.println(length.apply("Java"));
System.out.println(square.apply(6));
}
}4
36Check your understanding: What are T and R in Function<String,Integer>?
String is the input type; Integer is the result type.
Step 14 of 19
9.14 Consumer<T>
Perform an action with one input and no returned result.
import java.util.function.Consumer;
public class ConsumerDemo {
public static void main(String[] args) {
Consumer<String> display = name -> System.out.println(name);
display.accept("Amit");
}
}AmitCheck your understanding: What is Consumer’s main method?
accept(T value).
Step 15 of 19
9.15 Supplier<T>
Provide a value without receiving an argument.
import java.util.function.Supplier;
public class SupplierDemo {
public static void main(String[] args) {
Supplier<String> defaultValue = () -> "Java";
System.out.println(defaultValue.get());
}
}JavaCommon uses
- Generating values
- Creating objects
- Providing defaults
Check your understanding: Does Supplier accept an input parameter?
No.
Step 16 of 19
9.16 Comparison of Functional Interfaces
Compare input, output, and method contracts.
| Interface | Input | Output | Main method |
|---|---|---|---|
| Predicate<T> | One value | boolean | test() |
| Function<T,R> | One value | Another value | apply() |
| Consumer<T> | One value | No result | accept() |
| Supplier<T> | No input | One value | get() |
Check your understanding: Which interface has no input but produces a value?
Supplier<T>.
Step 17 of 19
9.17 Method References
Replace a lambda that only calls an existing method with :: syntax.
import java.util.Arrays;
import java.util.List;
public class MethodReferenceDemo {
public static void main(String[] args) {
List<String> names = Arrays.asList("Amit", "Neha", "Raj");
names.forEach(System.out::println);
}
}Amit
Neha
Rajname -> System.out.println(name)
System.out::printlnCheck your understanding: What operator introduces a method reference?
The double colon (::).
Step 18 of 19
9.18 Types of Method References
Recognize static, bound instance, unbound instance, and constructor references.
| Type | Form | Example |
|---|---|---|
| Static method | ClassName::staticMethod | Integer::parseInt |
| Particular object | object::instanceMethod | System.out::println |
| Arbitrary object | ClassName::instanceMethod | String::compareToIgnoreCase |
| Constructor | ClassName::new | ArrayList::new |
Check your understanding: Which form creates objects?
ClassName::new.
Step 19 of 19
9.19 Local Variables in Lambda Expressions
Apply the final-or-effectively-final capture rule.
import java.util.function.Function;
public class LambdaCaptureDemo {
public static void main(String[] args) {
int multiplier = 5; // effectively final
Function<Integer, Integer> multiply = number -> number * multiplier;
System.out.println(multiply.apply(4));
}
}20Check your understanding: Can a lambda capture multiplier after multiplier is reassigned?
No.