Java 8 Stream API: Declarative Data Processing with PO/VO Examples
This article introduces Java 8's Stream API, explains its SQL‑like pipeline operations such as filter, map, sorted, collect and parallelStream, and demonstrates practical PO/VO processing with comprehensive code examples and performance considerations.
Java 8 added a new abstraction called Stream, allowing data to be processed in a declarative way.
Streams provide an intuitive, SQL‑like approach to operate on Java collections, offering a high‑level abstraction for collection manipulation.
This style treats the collection of elements as a stream that flows through a pipeline where each node can perform operations such as filtering, sorting, or aggregation.
Linux users will recognize the similarity to the pipe (|) operator; the concept is essentially the same.
Compared with traditional for‑loop iteration, stream code is shorter and clearer, especially when handling multiple PO/VO objects, avoiding the "Russian doll" nesting that makes the code hard to read.
Stream
+--------------------+ +------+ +------+ +---+ +-------+
| stream of elements +----->|filter+->|sorted+->|map+->|collect|
+--------------------+ +------+ +------+ +---+ +-------+PO Code
All following operations use the UserPo class.
filter
filter: selects elements that satisfy a condition, discarding the rest.
// Count students whose score is not null
long count = list.stream().filter(p -> null != p.getScore()).count();map
map: transforms each element into a new form, commonly used to extract fields from PO/VO objects.
// Extract all student scores
List<Double> scoreList = list.stream().map(p -> p.getScore()).collect(Collectors.toList());
// Join all student names into a comma‑separated string
String nameString = list.stream().map(p -> p.getName()).collect(Collectors.joining(","));sorted
sorted: orders the stream according to a specified comparator; adding .reversed() sorts in descending order.
// Sort by score in descending order
List<UserPo> filterList = list.stream()
.filter(p -> null != p.getScore())
.sorted(Comparator.comparing(UserPo::getScore).reversed())
.collect(Collectors.toList());forEach
forEach: performs a custom action on each element; unlike other operations it can modify the original collection.
// Print each element
filterList.forEach(System.out::println);collect
collect: aggregates the stream, useful for grouping, converting to a list, or joining strings.
// Group by score
Map<Double, List<UserPo>> groupByScoreMap = list.stream()
.filter(p -> null != p.getScore())
.collect(Collectors.groupingBy(UserPo::getScore));
// Convert to list
List<Double> scoreList = list.stream().map(UserPo::getScore).collect(Collectors.toList());
// Join names
String nameString = list.stream().map(UserPo::getName).collect(Collectors.joining(","));statistics
statistics: provides summary statistics such as min, max, sum, average, and count.
DoubleSummaryStatistics stats = filterList.stream()
.mapToDouble(UserPo::getScore)
.summaryStatistics();
System.out.println("max=" + stats.getMax());
System.out.println("min=" + stats.getMin());
System.out.println("sum=" + stats.getSum());
System.out.println("avg=" + stats.getAverage());parallelStream
parallelStream: executes stream operations in parallel using multiple threads, which can improve performance but lacks thread‑local context.
long parallelCount = list.parallelStream()
.filter(p -> null != p.getScore())
.count();Complete Code
package com.cmx.tcn.stream;
/**
* @author: Cai MinXing
* @create: 2020-03-25 18:17
*/
public class UserPo {
private String name;
private Double score;
public UserPo(String name, Double score) {
this.name = name;
this.score = score;
}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Double getScore() { return score; }
public void setScore(Double score) { this.score = score; }
@Override
public String toString() {
return "UserPo{" + "name='" + name + '\'' + ", score=" + score + '}';
}
} package com.cmx.tcn.stream;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.DoubleSummaryStatistics;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author: Cai MinXing
* @create: 2020-03-25 18:15
*/
public class StreamTest {
public static void main(String[] args) {
List
list = new ArrayList<>();
list.add(new UserPo("XiaoYi", 10.0));
list.add(new UserPo("XiaoWu", 50.0));
list.add(new UserPo("XiaoLiu", 60.0));
list.add(new UserPo("Xiao6", 60.0));
list.add(new UserPo("XiaoKong", null));
list.add(new UserPo("XiaoJiu", 90.0));
long count = list.stream().filter(p -> null != p.getScore()).count();
System.out.println("Number of students who took the exam: " + count);
List
filterList = list.stream()
.filter(p -> null != p.getScore())
.collect(Collectors.toList());
System.out.println("Student info:");
filterList.forEach(System.out::println);
List
scoreList = list.stream().map(UserPo::getScore).collect(Collectors.toList());
System.out.println("All scores: " + scoreList);
String nameString = list.stream().map(UserPo::getName).collect(Collectors.joining(","));
System.out.println("All names: " + nameString);
filterList = list.stream()
.filter(p -> null != p.getScore())
.sorted(Comparator.comparing(UserPo::getScore).reversed())
.collect(Collectors.toList());
System.out.println("Scores sorted descending:");
filterList.forEach(System.out::println);
Map
> groupByScoreMap = list.stream()
.filter(p -> null != p.getScore())
.collect(Collectors.groupingBy(UserPo::getScore));
for (Map.Entry
> entry : groupByScoreMap.entrySet()) {
System.out.println("Score: " + entry.getKey() + " Count: " + entry.getValue().size());
}
// Increase each score by 10
filterList.forEach(p -> p.setScore(p.getScore() + 10));
System.out.println("Add 10 points to each student");
filterList.forEach(System.out::println);
long passCount = filterList.stream().filter(p -> p.getScore() >= 60).count();
System.out.println("Number of passing students: " + passCount);
DoubleSummaryStatistics statistics = filterList.stream()
.mapToDouble(UserPo::getScore)
.summaryStatistics();
System.out.println("Max: " + statistics.getMax());
System.out.println("Min: " + statistics.getMin());
System.out.println("Sum: " + statistics.getSum());
System.out.println("Avg: " + statistics.getAverage());
long parallelCount = list.parallelStream().filter(p -> null != p.getScore()).count();
System.out.println("Parallel stream count: " + parallelCount);
}
}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.