0

0

Java Stream API:高效处理和排序学生成绩数据

DDD

DDD

发布时间:2025-07-16 14:28:02

|

181人浏览过

|

来源于php中文网

原创

Java Stream API:高效处理和排序学生成绩数据

本文深入探讨如何利用Java Stream API高效处理学生成绩数据。我们将学习如何收集、计算学生平均分,并在此基础上进行过滤和降序排序,最终以指定格式输出结果。文章强调通过预计算平均分来优化性能,并利用Stream API的强大功能简化代码逻辑。

1. 数据收集与初始存储

在处理学生成绩数据时,通常需要将每个学生的多个成绩关联起来。一个常见的做法是使用 map> 来存储,其中键是学生姓名(string),值是该学生所有成绩的列表(list

以下代码片段展示了如何从标准输入读取学生姓名和成绩,并将其存储到 Map 中:

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> records = new HashMap<>();

        // 循环读取数据并存储
        while(n > 0){
            String name = scanner.nextLine();
            double grade = Double.parseDouble(scanner.nextLine());
            // 如果学生不存在,则添加新列表;否则,将成绩添加到现有列表
            records.putIfAbsent(name, new ArrayList<>());
            records.get(name).add(grade);
            n--;
        }
        // ... 后续处理
    }
}

2. Stream API处理的挑战与优化思路

在处理完原始数据后,我们需要执行以下操作:

  1. 计算每个学生的平均分。
  2. 过滤掉平均分低于特定阈值(例如 4.50)的学生。
  3. 根据平均分进行降序排序。
  4. 以指定格式打印结果。

最初的实现可能会在 filter 和 sorted 操作中多次计算平均分,这会导致性能下降。例如,在 sorted 操作的 Comparator 中再次计算平均分,不仅冗余,而且将 double 类型的差值强制转换为 int ((int) (average2 - average1)) 可能导致排序不准确,因为小数部分的差异会被截断。

为了解决这个问题,最佳实践是预先计算并存储平均分。我们可以将原始的 Map> 转换为 Map,其中键是学生姓名,值是其对应的平均分。

立即学习Java免费学习笔记(深入)”;

3. 预计算学生平均分

使用 Java Stream API 的 Collectors.toMap 可以优雅地完成这一转换:

// 将原始记录转换为包含平均分的Map
Map recordsWithAverage = records.entrySet()
    .stream()
    .collect(Collectors.toMap(
        Map.Entry::getKey, // 使用原始Map的键作为新Map的键(学生姓名)
        e -> e.getValue().stream().mapToDouble(x -> x).average().orElse(0.0) // 计算平均分,如果列表为空则默认为0.0
    ));

注意事项: average() 方法返回一个 OptionalDouble。为了避免在学生没有成绩时调用 getAsDouble() 抛出 NoSuchElementException,我们使用 orElse(0.0) 提供一个默认值(例如 0.0),尽管在本场景中,根据问题描述,每个学生都会有成绩。

Paraflow
Paraflow

AI产品设计智能体

下载

4. 过滤、排序与输出

有了包含平均分的 recordsWithAverage 之后,后续的过滤和排序操作将变得更加高效和简洁。

// 对包含平均分的Map进行过滤、排序和输出
recordsWithAverage.entrySet()
    .stream()
    .filter(e -> e.getValue() >= 4.50) // 过滤平均分大于或等于4.50的学生
    .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) // 按平均分降序排序
    .forEach(pair -> {
        // 格式化输出:姓名 -> 平均分 (保留两位小数)
        System.out.printf("%s -> %.2f%n", pair.getKey(), pair.getValue());
    });

代码解析:

  • filter(e -> e.getValue() >= 4.50):直接使用 Map.Entry 的值(即平均分)进行过滤。
  • sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())):这是排序的关键。
    • Map.Entry.comparingByValue():这是一个方便的 Comparator 工厂方法,它会创建一个 Comparator,用于比较 Map.Entry 对象的
    • Comparator.reverseOrder():用于将默认的升序排序转换为降序排序。通过组合这两个方法,我们实现了按平均分降序排序,无需手动编写复杂的 lambda 表达式。
  • forEach(pair -> System.out.printf("%s -> %.2f%n", pair.getKey(), pair.getValue())):遍历排序后的结果,并使用 printf 方法以指定格式输出,其中 %.2f 用于将 double 值格式化为保留两位小数的浮点数。

5. 完整代码示例

结合以上所有步骤,完整的解决方案如下:

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> records = new HashMap<>();
        while(n > 0){
            String name = scanner.nextLine();
            double grade = Double.parseDouble(scanner.nextLine());
            records.putIfAbsent(name, new ArrayList<>());
            records.get(name).add(grade);
            n--;
        }

        // 2. 预计算学生平均分
        Map recordsWithAverage = records.entrySet()
            .stream()
            .collect(Collectors.toMap(
                Map.Entry::getKey,
                e -> e.getValue().stream().mapToDouble(x -> x).average().orElse(0.0) // 处理空列表情况
            ));

        // 3. 过滤、排序与输出
        recordsWithAverage.entrySet()
            .stream()
            .filter(e -> e.getValue() >= 4.50) // 过滤平均分
            .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) // 按平均分降序排序
            .forEach(pair -> {
                System.out.printf("%s -> %.2f%n", pair.getKey(), pair.getValue()); // 格式化输出
            });

        scanner.close(); // 关闭Scanner
    }
}

总结

通过本教程,我们学习了如何使用 Java Stream API 高效地处理和排序复杂数据结构。核心优化点在于:

  1. 避免重复计算: 在进行过滤和排序之前,预先计算并存储派生值(如平均分),可以显著提高性能。
  2. 善用 Collectors: Collectors.toMap 等方法提供了强大的数据转换能力,能够将一种集合类型高效地转换为另一种。
  3. 利用 Comparator 工具方法: Map.Entry.comparingByValue() 和 Comparator.reverseOrder() 等 Comparator 工厂方法使排序逻辑更加简洁和易读,同时避免了 double 到 int 强制类型转换可能导致的精度问题。

掌握这些技巧,将有助于您编写更高效、更具可读性的 Java Stream API 代码。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

443

2023.08.02

php中foreach用法
php中foreach用法

本专题整合了php中foreach用法的相关介绍,阅读专题下面的文章了解更多详细教程。

74

2025.12.04

printf用法大全
printf用法大全

php中文网为大家提供printf用法大全,以及其他printf函数的相关文章、相关下载资源以及各种相关课程,供大家免费下载体验。

74

2023.06.20

fprintf和printf的区别
fprintf和printf的区别

fprintf和printf的区别在于输出的目标不同,printf输出到标准输出流,而fprintf输出到指定的文件流。根据需要选择合适的函数来进行输出操作。更多关于fprintf和printf的相关文章详情请看本专题下面的文章。php中文网欢迎大家前来学习。

285

2023.11.28

java进行强制类型转换
java进行强制类型转换

强制类型转换是Java中的一种重要机制,用于将一个数据类型转换为另一个数据类型。想了解更多强制类型转换的相关内容,可以阅读本专题下面的文章。

284

2023.12.01

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

443

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

544

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

73

2025.08.29

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

10

2026.01.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 4.2万人学习

Pandas 教程
Pandas 教程

共15课时 | 1.0万人学习

ASP 教程
ASP 教程

共34课时 | 4.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号