实战:集合应用

本课是Phase 4的综合实战,通过学生成绩管理系统巩固集合知识。

项目需求

实现一个学生成绩管理系统,支持:

数据模型

JAVA
import java.util.ArrayList;
import java.util.List;

public class Student {
    private String id;
    private String name;
    private List<Subject> subjects;
    
    public Student(String id, String name) {
        this.id = id;
        this.name = name;
        this.subjects = new ArrayList<>();
    }
    
    public String getId() { return id; }
    public String getName() { return name; }
    public List<Subject> getSubjects() { return subjects; }
    
    public void addSubject(String name, int score) {
        subjects.add(new Subject(name, score));
    }
    
    public double getAverage() {
        if (subjects.isEmpty()) return 0;
        return subjects.stream()
            .mapToInt(Subject::getScore)
            .average()
            .orElse(0);
    }
    
    public int getTotal() {
        return subjects.stream()
            .mapToInt(Subject::getScore)
            .sum();
    }
    
    @Override
    public String toString() {
        return name + " (ID:" + id + ", 平均分:" + String.format("%.1f", getAverage()) + ")";
    }
}

public class Subject {
    private String name;
    private int score;
    
    public Subject(String name, int score) {
        this.name = name;
        this.score = score;
    }
    
    public String getName() { return name; }
    public int getScore() { return score; }
    
    @Override
    public String toString() {
        return name + ":" + score;
    }
}

管理类

JAVA
import java.util.*;
import java.util.stream.Collectors;

public class GradeManager {
    private Map<String, Student> students;
    
    public GradeManager() {
        this.students = new LinkedHashMap<>();
    }
    
    // 添加学生
    public void addStudent(Student student) {
        students.put(student.getId(), student);
        System.out.println("添加学生:" + student.getName());
    }
    
    // 添加成绩
    public void addScore(String studentId, String subject, int score) {
        Student student = students.get(studentId);
        if (student != null) {
            student.addSubject(subject, score);
            System.out.println(student.getName() + " " + subject + " " + score);
        } else {
            System.out.println("学生不存在:" + studentId);
        }
    }
    
    // 查询学生
    public Student findStudent(String id) {
        return students.get(id);
    }
    
    // 按平均分排序
    public List<Student> sortByAverage() {
        return students.values().stream()
            .sorted((a, b) -> Double.compare(b.getAverage(), a.getAverage()))
            .collect(Collectors.toList());
    }
    
    // 按总分排序
    public List<Student> sortByTotal() {
        return students.values().stream()
            .sorted((a, b) -> Integer.compare(b.getTotal(), a.getTotal()))
            .collect(Collectors.toList());
    }
    
    // 统计平均分
    public double getAverageScore() {
        return students.values().stream()
            .mapToDouble(Student::getAverage)
            .average()
            .orElse(0);
    }
    
    // 统计最高分
    public Student getTopStudent() {
        return students.values().stream()
            .max(Comparator.comparingDouble(Student::getAverage))
            .orElse(null);
    }
    
    // 统计最低分
    public Student getBottomStudent() {
        return students.values().stream()
            .min(Comparator.comparingDouble(Student::getAverage))
            .orElse(null);
    }
    
    // 按等级分组
    public Map<String, List<Student>> groupByGrade() {
        return students.values().stream()
            .collect(Collectors.groupingBy(student -> {
                double avg = student.getAverage();
                if (avg >= 90) return "优秀";
                if (avg >= 80) return "良好";
                if (avg >= 70) return "中等";
                if (avg >= 60) return "及格";
                return "不及格";
            }));
    }
    
    // 获取所有学生
    public List<Student> getAllStudents() {
        return new ArrayList<>(students.values());
    }
}

主程序

JAVA
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class GradeSystem {
    private static GradeManager manager = new GradeManager();
    private static Scanner scanner = new Scanner(System.in);
    
    public static void main(String[] args) {
        // 初始化数据
        initData();
        
        // 主循环
        int choice;
        do {
            showMenu();
            choice = scanner.nextInt();
            scanner.nextLine();
            
            switch (choice) {
                case 1: listStudents(); break;
                case 2: addScore(); break;
                case 3: viewStudent(); break;
                case 4: showRanking(); break;
                case 5: showStatistics(); break;
                case 6: showGroups(); break;
                case 0: System.out.println("再见!"); break;
                default: System.out.println("无效选择");
            }
        } while (choice != 0);
        
        scanner.close();
    }
    
    private static void initData() {
        Student s1 = new Student("S001", "Alice");
        s1.addSubject("Java", 95);
        s1.addSubject("Python", 88);
        s1.addSubject("数据库", 92);
        
        Student s2 = new Student("S002", "Bob");
        s2.addSubject("Java", 85);
        s2.addSubject("Python", 90);
        s2.addSubject("数据库", 78);
        
        Student s3 = new Student("S003", "Charlie");
        s3.addSubject("Java", 78);
        s3.addSubject("Python", 82);
        s3.addSubject("数据库", 88);
        
        manager.addStudent(s1);
        manager.addStudent(s2);
        manager.addStudent(s3);
    }
    
    private static void showMenu() {
        System.out.println("\n=== 学生成绩管理系统 ===");
        System.out.println("1. 查看所有学生");
        System.out.println("2. 添加成绩");
        System.out.println("3. 查看学生详情");
        System.out.println("4. 成绩排名");
        System.out.println("5. 统计分析");
        System.out.println("6. 等级分组");
        System.out.println("0. 退出");
        System.out.print("请选择:");
    }
    
    private static void listStudents() {
        System.out.println("\n--- 学生列表 ---");
        for (Student s : manager.getAllStudents()) {
            System.out.println(s);
        }
    }
    
    private static void addScore() {
        System.out.print("请输入学生ID:");
        String id = scanner.nextLine();
        System.out.print("请输入科目:");
        String subject = scanner.nextLine();
        System.out.print("请输入分数:");
        int score = scanner.nextInt();
        scanner.nextLine();
        
        manager.addScore(id, subject, score);
    }
    
    private static void viewStudent() {
        System.out.print("请输入学生ID:");
        String id = scanner.nextLine();
        
        Student student = manager.findStudent(id);
        if (student != null) {
            System.out.println("\n--- " + student.getName() + "的成绩 ---");
            for (Subject s : student.getSubjects()) {
                System.out.println(s);
            }
            System.out.printf("总分:%d,平均分:%.1f%n", 
                student.getTotal(), student.getAverage());
        } else {
            System.out.println("学生不存在");
        }
    }
    
    private static void showRanking() {
        System.out.println("\n--- 成绩排名 ---");
        List<Student> ranking = manager.sortByAverage();
        for (int i = 0; i < ranking.size(); i++) {
            Student s = ranking.get(i);
            System.out.printf("%d. %s - 平均分:%.1f%n", 
                i + 1, s.getName(), s.getAverage());
        }
    }
    
    private static void showStatistics() {
        System.out.println("\n=== 统计分析 ===");
        System.out.printf("全班平均分:%.1f%n", manager.getAverageScore());
        
        Student top = manager.getTopStudent();
        if (top != null) {
            System.out.printf("最高分:%s - %.1f%n", top.getName(), top.getAverage());
        }
        
        Student bottom = manager.getBottomStudent();
        if (bottom != null) {
            System.out.printf("最低分:%s - %.1f%n", bottom.getName(), bottom.getAverage());
        }
    }
    
    private static void showGroups() {
        System.out.println("\n=== 等级分组 ===");
        Map<String, List<Student>> groups = manager.groupByGrade();
        
        groups.forEach((grade, students) -> {
            System.out.println("\n" + grade + "(" + students.size() + "人):");
            students.forEach(s -> 
                System.out.println("  " + s.getName() + " - " + String.format("%.1f", s.getAverage())));
        });
    }
}

运行示例

TEXT
=== 学生成绩管理系统 ===
1. 查看所有学生
2. 添加成绩
3. 查看学生详情
4. 成绩排名
5. 统计分析
6. 等级分组
0. 退出
请选择:4

--- 成绩排名 ---
1. Alice - 平均分:91.7
2. Bob - 平均分:84.3
3. Charlie - 平均分:82.7

设计要点

要点 说明
Map存储 用Map按ID索引学生
List存储 用List存储科目成绩
Stream操作 用Stream进行排序、统计、分组
Comparator 自定义排序规则
Collectors.groupingBy 按等级分组

扩展功能

成绩导出

JAVA
public void exportToFile(String filename) {
    try (PrintWriter writer = new PrintWriter(new FileWriter(filename))) {
        writer.println("ID,姓名,Java,Python,数据库,总分,平均分");
        for (Student s : students.values()) {
            writer.printf("%s,%s,%s,%d,%.1f%n",
                s.getId(), s.getName(),
                s.getSubjects().stream()
                    .map(sub -> String.valueOf(sub.getScore()))
                    .collect(Collectors.joining(",")),
                s.getTotal(), s.getAverage());
        }
        System.out.println("导出成功:" + filename);
    } catch (IOException e) {
        System.out.println("导出失败:" + e.getMessage());
    }
}

按科目统计

JAVA
public Map<String, Double> getSubjectAverages() {
    Map<String, List<Integer>> subjectScores = new HashMap<>();
    
    for (Student student : students.values()) {
        for (Subject subject : student.getSubjects()) {
            subjectScores.computeIfAbsent(subject.getName(), k -> new ArrayList<>())
                .add(subject.getScore());
        }
    }
    
    return subjectScores.entrySet().stream()
        .collect(Collectors.toMap(
            Map.Entry::getKey,
            e -> e.getValue().stream().mapToInt(Integer::intValue).average().orElse(0)
        ));
}

❓ 常见问题

Q 如何支持多班级?
A 用Map<String, GradeManager>存储多个班级。
Q 数据如何持久化?
A 可以使用文件IO或数据库存储。
Q 如何支持导入功能?
A 读取CSV文件,解析后创建Student对象。

📖 小节

📝 作业

  1. 导入功能: 从CSV文件导入学生成绩
  2. 按科目统计: 统计每科的平均分、最高分、最低分
  3. 成绩查询: 支持按姓名模糊查询

下一课

下一课我们将进入Phase 5,学习 文件IO,了解文件操作。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏