Using Java Lambda Expressions to Simplify Collection Operations
This article explains how Java lambda expressions and the Stream API can replace verbose loops, comparators, and aggregation code with concise, readable functional constructs, covering traversal, sorting, aggregation, optional handling, thread creation, mapping, grouping, and parallel processing of collections.
Many developers find Java lambda expressions unfamiliar and think they reduce code readability, but after practice these concerns often disappear.
A gradual adoption strategy—starting with simple, low‑risk cases—helps ease the transition to lambda usage.
Below are several common collection‑related scenarios rewritten with lambda expressions and the Stream API, demonstrating more concise and expressive code.
1. Traversing and filtering collections
Traditional loop:
List
numbers = Arrays.asList(1, 2, 3, 4, 5);
for (Integer num : numbers) {
if (num % 2 == 0) {
System.out.println(num);
}
}Lambda version:
List
numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.stream()
.filter(num -> num % 2 == 0)
.forEach(System.out::println);2. Sorting collections
Traditional comparator:
List
names = Arrays.asList("Alice", "Bob", "Charlie", "David");
Collections.sort(names, new Comparator
() {
public int compare(String name1, String name2) {
return name1.compareTo(name2);
}
});Lambda version:
List
names = Arrays.asList("Alice", "Bob", "Charlie", "David");
names.sort((name1, name2) -> name1.compareTo(name2));3. Aggregating collection elements
Traditional sum:
List
numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = 0;
for (Integer num : numbers) {
sum += num;
}Lambda version:
List
numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
.reduce(0, Integer::sum);4. Conditional filtering and default values
Traditional if‑else:
String name = "Alice";
if (name != null && name.length() > 0) {
System.out.println("Hello, " + name);
} else {
System.out.println("Hello, Stranger");
}Lambda with Optional:
String name = "Alice";
name = Optional.ofNullable(name)
.filter(n -> n.length() > 0)
.orElse("Stranger");
System.out.println("Hello, " + name);5. Simplifying anonymous inner classes
Creating a thread with a Runnable:
new Thread(new Runnable() {
public void run() {
System.out.println("Thread is running.");
}
}).start();Lambda version:
new Thread(() -> System.out.println("Thread is running.")).start();Lambda is also useful for callbacks, e.g., a functional interface Calculator and a method operate that receives a lambda to perform arithmetic.
6. Transforming collection elements
Traditional mapping:
List
names = Arrays.asList("Alice", "Bob", "Charlie");
List
uppercaseNames = new ArrayList<>();
for (String name : names) {
uppercaseNames.add(name.toUpperCase());
}Lambda version:
List
names = Arrays.asList("Alice", "Bob", "Charlie");
List
uppercaseNames = names.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());7. Grouping and counting
Traditional grouping and counting code is omitted for brevity; the lambda version uses groupingBy and count stream operations to achieve the same results more fluently.
8. Parallel processing of large collections
A program that creates one million random integers and computes the average using sequential and parallel streams demonstrates that parallel streams can significantly reduce execution time for large data sets.
Finally, lambda expressions are applicable beyond collections—such as in multithreading and file I/O—allowing developers to write more concise, expressive, and maintainable Java code.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
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.