简介
Java 流 API 提供了强大的数据处理能力,使开发者能够使用函数式编程技术高效地操作和收集数据。本教程将探索收集流结果的各种方法,展示如何用简洁且富有表现力的代码来转换和聚合数据。
Java 流 API 提供了强大的数据处理能力,使开发者能够使用函数式编程技术高效地操作和收集数据。本教程将探索收集流结果的各种方法,展示如何用简洁且富有表现力的代码来转换和聚合数据。
在 Java 中,流是支持顺序和并行聚合操作的元素序列。流在 Java 8 中引入,为处理对象集合提供了一种声明式方法。
| 特性 | 描述 |
|---|---|
| 函数式 | 支持函数式风格的操作 |
| 延迟求值 | 操作仅在需要时才计算 |
| 不可变 | 原始数据源保持不变 |
| 可消费 | 只能遍历一次 |
// 从集合创建流
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
Stream<String> nameStream = names.stream();
// Stream.of() 方法
Stream<Integer> numberStream = Stream.of(1, 2, 3, 4, 5);
// 流生成
Stream<String> infiniteStream = Stream.generate(() -> "Hello");
stream() 方法parallelStream() 方法filter():根据谓词选择元素map():转换元素sorted():对流元素进行排序collect():收集流结果forEach():对每个元素执行操作reduce():将流缩减为单个值List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
.filter(n -> n % 2 == 0)
.mapToInt(n -> n * 2)
.sum();
// 结果:12 (2 * 2 + 4 * 2)
通过理解这些流基础,开发者可以在 Java 中利用强大、简洁的数据处理技术。LabEx 建议实践这些概念以有效掌握流操作。
收集器是终端操作,用于将流元素转换为集合或聚合值。Collectors 类提供了许多预定义的方法来收集流结果。
| 收集器方法 | 描述 | 返回类型 |
|---|---|---|
toList() |
将元素收集到列表中 | List |
toSet() |
将唯一元素收集到集合中 | Set |
toCollection() |
收集到特定的集合中 | Collection |
joining() |
连接流元素 | String |
counting() |
对流元素进行计数 | Long |
// 收集到列表
List<String> nameList = names.stream()
.collect(Collectors.toList());
// 收集到集合
Set<String> uniqueNames = names.stream()
.collect(Collectors.toSet());
// 收集到特定集合
LinkedList<String> linkedNames = names.stream()
.collect(Collectors.toCollection(LinkedList::new));
// 按长度分组
Map<Integer, List<String>> groupedByLength = names.stream()
.collect(Collectors.groupingBy(String::length));
// 使用下游收集器分组
Map<Integer, Long> countByLength = names.stream()
.collect(Collectors.groupingBy(
String::length,
Collectors.counting()
));
// 分成两组
Map<Boolean, List<String>> partitioned = names.stream()
.collect(Collectors.partitioningBy(
name -> name.length() > 4
));
// 整数之和
int total = numbers.stream()
.collect(Collectors.summingInt(Integer::intValue));
// 汇总统计信息
IntSummaryStatistics stats = numbers.stream()
.collect(Collectors.summarizingInt(Integer::intValue));
// 简单连接
String result = names.stream()
.collect(Collectors.joining());
// 用分隔符连接
String commaSeparated = names.stream()
.collect(Collectors.joining(", "));
// 自定义收集器
List<String> customCollected = names.stream()
.collect(
ArrayList::new,
ArrayList::add,
ArrayList::addAll
);
LabEx 建议实践这些收集操作,以熟练掌握流处理技术。
class Employee {
private String name;
private double salary;
private Department department;
// 构造函数、getter 和 setter
}
// 筛选高绩效员工
List<Employee> topPerformers = employees.stream()
.filter(e -> e.getSalary() > 50000)
.filter(e -> e.getDepartment() == Department.ENGINEERING)
.collect(Collectors.toList());
// 按部门计算平均薪资
Map<Department, Double> avgSalaryByDept = employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.averagingDouble(Employee::getSalary)
));
// 提取唯一姓名
Set<String> uniqueNames = employees.stream()
.map(Employee::getName)
.collect(Collectors.toSet());
// 创建姓名 - 薪资映射
Map<String, Double> nameSalaryMap = employees.stream()
.collect(Collectors.toMap(
Employee::getName,
Employee::getSalary
));
| 处理类型 | 特点 | 使用场景 |
|---|---|---|
| 顺序处理 | 单线程 | 小数据集 |
| 并行处理 | 多线程 | 大数据集 |
// 对大型员工列表进行并行处理
double totalSalary = employees.parallelStream()
.mapToDouble(Employee::getSalary)
.sum();
// 复杂条件过滤
List<Employee> seniorEngineers = employees.stream()
.filter(e -> e.getDepartment() == Department.ENGINEERING)
.filter(e -> e.getExperience() > 5)
.filter(e -> e.getSalary() > 75000)
.collect(Collectors.toList());
// 用于找出前 N 名员工的自定义收集器
Collector<Employee,?, List<Employee>> topNCollector =
Collectors.collectingAndThen(
Collectors.toList(),
list -> list.stream()
.sorted(Comparator.comparing(Employee::getSalary).reversed())
.limit(5)
.collect(Collectors.toList())
);
List<Employee> topFiveEmployees = employees.stream()
.collect(topNCollector);
// 带有异常处理的安全处理
List<String> processedData = rawData.stream()
.map(this::safeProcessing)
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
流提供了强大且灵活的数据处理能力。LabEx 建议持续练习以有效掌握这些技术。
理解 Java 中的流结果收集对于编写简洁、高效且具有函数式风格的代码至关重要。通过掌握不同的收集技术和收集器,开发者能够简化数据处理、提高代码可读性,并充分利用 Java 流 API 的全部潜力来进行复杂的数据转换。