11
小项目实战:学生成绩管理系统(控制台版)
Mini Project · Collections + IO + Threads
学了一堆零件,拼个真东西才算数。下面这个控制台小程序,把前面的集合、record、IO、Scanner 输入、多线程全串起来:能添加学生、按分数排序、存盘到文件、再加载回来。代码不长,建议逐行敲一遍跑通。
StudentManager.java:一个能跑的完整小项目
import java.nio.file.*;
import java.util.*;
import java.util.concurrent.*;
// 用 record 定义学生:姓名、学号、分数
record Student(String id, String name, double score) {}
public class StudentManager {
private static final List<Student> students = new ArrayList<>();
private static final Path FILE = Path.of("students.txt");
private static final Scanner SC = new Scanner(System.in);
public static void main(String[] args) throws Exception {
loadFromFile(); // 启动时先读档
while (true) {
System.out.println("\n1 添加 2 列表 3 按分数排序 4 保存 5 退出");
System.out.print("选:");
int op = SC.nextInt();
switch (op) {
case 1 -> add();
case 2 -> list();
case 3 -> sortByScore();
case 4 -> saveToFile();
case 5 -> { saveToFile(); System.exit(0); }
default -> System.out.println("没这个选项");
}
}
}
static void add() {
System.out.print("> 学号 姓名 分数:");
students.add(new Student(SC.next(), SC.next(), SC.nextDouble()));
}
static void list() {
students.forEach(System.out::println);
}
static void sortByScore() {
students.stream()
.sorted(Comparator.comparingDouble(Student::score).reversed())
.forEach(System.out::println);
}
// 保存:把每个学生拼成一行,写入文件
static void saveToFile() throws Exception {
List<String> lines = students.stream()
.map(s -> s.id() + "," + s.name() + "," + s.score())
.toList();
Files.write(FILE, lines, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
System.out.println("已保存 " + students.size() + " 条");
}
// 加载:读文件,每行用逗号拆成三个字段
static void loadFromFile() throws Exception {
if (!Files.exists(FILE)) return;
for (String line : Files.readAllLines(FILE)) {
String[] parts = line.split(",");
students.add(new Student(parts[0], parts[1], Double.parseDouble(parts[2])));
}
}
}
跑起来大概长这样(控制台输出)
1 添加 2 列表 3 按分数排序 4 保存 5 退出
选:1
> 学号 姓名 分数:001 小明 92
选:1
> 学号 姓名 分数:002 小红 88
选:3
Student[id=001, name=小明, score=92.0]
Student[id=002, name=小红, score=88.0]
选:4
已保存 2 条
选:5
论这个小项目藏了哪些知识点
看着简单,其实每一步都在考试点:record 定义数据、ArrayList 存数据、switch 新写法做菜单、Stream + Comparator 排序、Files.readAllLines / write 做持久化、split 解析文本。把它敲通,Java 基础就算立住了。
扩展练习:① 加一个"按学号删除"功能;② 用虚拟线程在保存时后台打印"保存中..."动画;③ 把文件格式换成 JSON(引入一个第三方库)。每加一个功能,你就多踩一个真实的坑。
章末面试 · 综合实战(3 题)
1.(设计题)这个小项目如果要改成多线程并发保存文件,要注意什么?
查看答案
答案:students 是共享静态 List,多线程写会竞态。要么用线程安全集合(CopyOnWriteArrayList),要么加锁。保存到文件时也要防两个线程同时写同一个文件。
2.(扩展题)要加"按学号删除"功能,怎么写?
查看答案
答案:students.removeIf(s -> s.id().equals(targetId)),用 removeIf 而不是 for-each 里 remove,避免并发修改异常。
3.(思考题)为什么学生类用 record 不用普通类?
查看答案
答案:学生是纯数据载体,不需要可变状态。record 一行搞定,自动生成 toString/equals/带 getter,代码量少一半。