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<UserPo> 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<UserPo> filterList = list.stream()
.filter(p -> null != p.getScore())
.collect(Collectors.toList());
System.out.println("Student info:");
filterList.forEach(System.out::println);
List<Double> 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<Double, List<UserPo>> groupByScoreMap = list.stream()
.filter(p -> null != p.getScore())
.collect(Collectors.groupingBy(UserPo::getScore));
for (Map.Entry<Double, List<UserPo>> 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);
}
}Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
