
在数据处理场景中,我们经常需要对集合数据进行转换、筛选和排序。以学生成绩管理为例,常见的需求包括:收集学生的各科成绩,计算平均分,筛选出符合特定条件的(如平均分高于某个阈值)学生,并按平均分高低进行排序。Java 8引入的Stream API为这类数据处理提供了强大而简洁的解决方案。
本教程将演示如何使用Java Stream API来解决以下问题:
首先,我们需要从标准输入读取数据。学生姓名和成绩是交替输入的,并且每个学生可能有多个成绩。为了存储这些数据,一个 Map<String, List<Double>> 是一个非常合适的选择,其中键是学生姓名,值是该学生所有成绩的列表。
import java.util.*;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = Integer.parseInt(scanner.nextLine()); // 读取学生/成绩对的数量
// 使用Map存储学生姓名及其对应的成绩列表
Map<String, List<Double>> studentRecords = new HashMap<>();
// 循环读取n对学生姓名和成绩
while (n > 0) {
String name = scanner.nextLine();
double grade = Double.parseDouble(scanner.nextLine());
// 如果学生不存在,则创建新的成绩列表;否则,将成绩添加到现有列表中
studentRecords.putIfAbsent(name, new ArrayList<>());
studentRecords.get(name).add(grade);
n--;
}
// 关闭Scanner,释放资源
scanner.close();
// 后续处理将基于这个 studentRecords Map
}
}在上述代码中,putIfAbsent 方法确保如果学生姓名首次出现,会为他创建一个新的 ArrayList 来存储成绩。
立即学习“Java免费学习笔记(深入)”;
原始问题中,用户在 filter 和 sorted 操作中都重复计算了学生的平均分,这会导致性能下降。更优的方法是先计算出每个学生的平均分,将其存储在一个新的 Map<String, Double> 中,然后再对这个新的Map进行筛选和排序。
我们可以使用Stream API的 collect(Collectors.toMap(...)) 操作将 Map<String, List<Double>> 转换为 Map<String, Double>,其中值是计算好的平均分。
// 将原始学生成绩Map转换为学生姓名和其平均分的Map
Map<String, Double> studentAverages = studentRecords.entrySet()
.stream()
.collect(Collectors.toMap(
Map.Entry::getKey, // 使用原始Map的键(学生姓名)作为新Map的键
entry -> entry.getValue().stream() // 获取成绩列表
.mapToDouble(Double::doubleValue) // 转换为DoubleStream
.average() // 计算平均值
.orElse(0.0) // 如果没有成绩(理论上不会发生),默认平均分为0.0
));这一步是性能优化的关键。通过一次性计算并存储平均分,避免了在后续的过滤和排序操作中重复执行耗时的平均分计算。
有了 studentAverages 这个 Map<String, Double>,接下来的筛选和排序就变得非常直接和高效。
// 对包含平均分的Map进行筛选、排序和输出
studentAverages.entrySet()
.stream()
.filter(entry -> entry.getValue() >= 4.50) // 筛选平均分大于或等于4.50的学生
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) // 按平均分降序排序
.forEach(pair -> {
// 格式化输出,平均分保留两位小数
System.out.printf("%s -> %.2f%n", pair.getKey(), pair.getValue());
});将以上所有部分整合,构成一个完整的Java程序:
import java.util.*;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = Integer.parseInt(scanner.nextLine());
// 1. 数据收集:存储学生姓名及其所有成绩
Map<String, List<Double>> studentRecords = new HashMap<>();
while (n > 0) {
String name = scanner.nextLine();
double grade = Double.parseDouble(scanner.nextLine());
studentRecords.putIfAbsent(name, new ArrayList<>());
studentRecords.get(name).add(grade);
n--;
}
scanner.close();
// 2. 预计算平均分:将学生成绩Map转换为学生平均分Map
Map<String, Double> studentAverages = studentRecords.entrySet()
.stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> entry.getValue().stream()
.mapToDouble(Double::doubleValue)
.average()
.orElse(0.0) // 处理无成绩的情况,尽管本例输入不会出现
));
// 3. 筛选、排序并输出:
studentAverages.entrySet()
.stream()
.filter(entry -> entry.getValue() >= 4.50) // 筛选平均分 >= 4.50 的学生
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) // 按平均分降序排序
.forEach(pair -> {
System.out.printf("%s -> %.2f%n", pair.getKey(), pair.getValue()); // 格式化输出
});
}
}通过上述方法,我们能够利用Java Stream API以声明式、高效的方式处理复杂的集合数据操作,使代码更具可读性和维护性。
以上就是Java Stream API:高效处理与排序学生平均成绩的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号