Introduction to Java Lambda Expressions and Common Usage Examples
This article introduces Java Lambda expressions, explains the functional interface requirements, demonstrates basic and simplified syntax, and provides numerous practical examples such as method references, constructor references, thread creation, collection iteration, element removal, sorting, and closure behavior.
Lambda Introduction
Lambda expressions are a new feature in JDK 8 that can replace most anonymous inner classes, allowing more elegant Java code, especially for collection traversal and other operations, greatly improving code structure.
JDK also provides many built‑in functional interfaces, making the use of Lambdas convenient and efficient.
Requirements for Interfaces
Although Lambdas can provide simple implementations for some interfaces, not all interfaces are suitable; a Lambda can only be used when the interface has exactly one abstract method to implement.
In JDK 8, the default keyword allows methods to have a default implementation, which does not affect Lambda usage.
@FunctionalInterface
The @FunctionalInterface annotation marks a functional interface, requiring that it contain only one abstract method; it is often used together with Lambda expressions.
Basic Lambda Syntax
Six functional interfaces are defined below and will be used throughout the examples.
/** Multi‑parameter, no return */
@FunctionalInterface
public interface NoReturnMultiParam {
void method(int a, int b);
}
/** No‑parameter, no return */
@FunctionalInterface
public interface NoReturnNoParam {
void method();
}
/** Single‑parameter, no return */
@FunctionalInterface
public interface NoReturnOneParam {
void method(int a);
}
/** Multi‑parameter, returns int */
@FunctionalInterface
public interface ReturnMultiParam {
int method(int a, int b);
}
/** No‑parameter, returns int */
@FunctionalInterface
public interface ReturnNoParam {
int method();
}
/** Single‑parameter, returns int */
@FunctionalInterface
public interface ReturnOneParam {
int method(int a);
}The syntax is () -> {} , where () describes the parameter list, {} the method body, and -> is the lambda operator.
import lambda.interfaces.*;
public class Test1 {
public static void main(String[] args) {
// No‑parameter, no return
NoReturnNoParam noReturnNoParam = () -> {
System.out.println("NoReturnNoParam");
};
noReturnNoParam.method();
// Single‑parameter, no return
NoReturnOneParam noReturnOneParam = (int a) -> {
System.out.println("NoReturnOneParam param:" + a);
};
noReturnOneParam.method(6);
// Multi‑parameter, no return
NoReturnMultiParam noReturnMultiParam = (int a, int b) -> {
System.out.println("NoReturnMultiParam param:" + "{" + a + "," + b + "}");
};
noReturnMultiParam.method(6, 8);
// No‑parameter, returns int
ReturnNoParam returnNoParam = () -> {
System.out.print("ReturnNoParam");
return 1;
};
int res = returnNoParam.method();
System.out.println("return:" + res);
// Single‑parameter, returns int
ReturnOneParam returnOneParam = (int a) -> {
System.out.println("ReturnOneParam param:" + a);
return 1;
};
int res2 = returnOneParam.method(6);
System.out.println("return:" + res2);
// Multi‑parameter, returns int
ReturnMultiParam returnMultiParam = (int a, int b) -> {
System.out.println("ReturnMultiParam param:" + "{" + a + "," + b + "}");
return 1;
};
int res3 = returnMultiParam.method(6, 8);
System.out.println("return:" + res3);
}
}Simplified Lambda Syntax
Further simplifications can be made by observing the following code.
import lambda.interfaces.*;
public class Test2 {
public static void main(String[] args) {
// 1. Omit parameter types (all parameters must be omitted)
NoReturnMultiParam lambda1 = (a, b) -> {
System.out.println("Simplify parameter types");
};
lambda1.method(1, 2);
// 2. Omit parentheses for a single parameter
NoReturnOneParam lambda2 = a -> {
System.out.println("Simplify parentheses");
};
lambda2.method(1);
// 3. Omit braces when the body has a single statement
NoReturnNoParam lambda3 = () -> System.out.println("Simplify braces");
lambda3.method();
// 4. Omit braces for a single return statement
ReturnOneParam lambda4 = a -> a + 3;
System.out.println(lambda4.method(5));
// 5. Concise multi‑parameter return
ReturnMultiParam lambda5 = (a, b) -> a + b;
System.out.println(lambda5.method(1, 1));
}
}Common Lambda Expression Examples
Method Reference in Lambda
Sometimes we can refer directly to an already implemented method instead of writing a new anonymous class.
Syntax
ClassName::methodName for static methods, or instance::methodName for instance methods.
public class Exe1 {
public static void main(String[] args) {
ReturnOneParam lambda1 = a -> doubleNum(a);
System.out.println(lambda1.method(3));
// Method reference to static method
ReturnOneParam lambda2 = Exe1::doubleNum;
System.out.println(lambda2.method(3));
Exe1 exe = new Exe1();
// Method reference to instance method
ReturnOneParam lambda4 = exe::addTwo;
System.out.println(lambda4.method(2));
}
public static int doubleNum(int a) {
return a * 2;
}
public int addTwo(int a) {
return a + 2;
}
}Constructor Reference
Interfaces can act as object factories; using ClassName::new creates instances.
interface ItemCreatorBlankConstruct {
Item getItem();
}
interface ItemCreatorParamContruct {
Item getItem(int id, String name, double price);
}
public class Exe2 {
public static void main(String[] args) {
ItemCreatorBlankConstruct creator = () -> new Item();
Item item = creator.getItem();
ItemCreatorBlankConstruct creator2 = Item::new;
Item item2 = creator2.getItem();
ItemCreatorParamContruct creator3 = Item::new;
Item item3 = creator3.getItem(112, "Mouse", 135.99);
}
}Creating Threads with Lambda
Instead of an anonymous inner class overriding run() , a Lambda can be used.
Thread t = new Thread(() -> {
for (int i = 0; i < 10; i++) {
System.out.println(2 + ":" + i);
}
});
t.start();Iterating Collections
The forEach(Consumer action) method can be used with Lambdas to traverse elements.
@FunctionalInterface
public interface Consumer
{
void accept(T t);
// ...
} ArrayList
list = new ArrayList<>();
Collections.addAll(list, 1, 2, 3, 4, 5);
list.forEach(System.out::println);
list.forEach(element -> {
if (element % 2 == 0) {
System.out.println(element);
}
});Removing Elements from a Collection
The removeIf(Predicate filter) method removes elements that match a condition.
ArrayList
items = new ArrayList<>();
items.add(new Item(11, "Toothbrush", 12.05));
items.add(new Item(5, "Japanese toilet seat", 999.05));
items.add(new Item(7, "Gree air conditioner", 888.88));
items.add(new Item(17, "Soap", 2.00));
items.add(new Item(9, "Refrigerator", 4200.00));
items.removeIf(ele -> ele.getId() == 7);
items.forEach(System.out::println);Sorting Elements in a Collection
Lambda expressions simplify sorting with a comparator.
ArrayList
list = new ArrayList<>();
list.add(new Item(13, "Vest", 7.80));
list.add(new Item(11, "Half‑sleeve", 37.80));
list.add(new Item(14, "Windbreaker", 139.80));
list.add(new Item(12, "Thermal pants", 55.33));
list.sort((o1, o2) -> o1.getId() - o2.getId());
System.out.println(list);Closure Issue in Lambda Expressions
Like anonymous inner classes, Lambdas capture variables; the captured variable is effectively final and cannot be modified after capture.
import java.util.function.Consumer;
public class Main {
public static void main(String[] args) {
int num = 10;
Consumer
consumer = ele -> {
System.out.println(num);
};
// num = num + 2; // illegal – would cause a compile‑time error
consumer.accept("hello");
}
}Architect's Tech Stack
Java backend, microservices, distributed systems, containerized programming, and more.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.