学习前提
完成Java集合、异常、UTF-8文件读写;理解按键累加。
本课完成后你能做什么
整合输入验证、集合和稳定排序,保留错误行号。
先理解机制
先约定输入格式:每行课程名和整分钟,用一个分号分隔,课程名不能包含分号。它是本项目的简易格式,不是支持引号和转义的通用CSV解析器。
解析、验证、累计、展示分别进行。split使用-1保留末尾空字段,否则"Java;"可能丢失空值信息。错误记录保存从1开始的原始行号,不能先过滤再重新编号。
只让合法行参与总计。Map使用Long累计,TreeMap保证课程名顺序;错误列表单独展示,避免不完整数据看起来像完整成功。这里采用ASCII课程名,排序不是中文拼音规则。
可运行示例
使用JDK 21。将代码保存为Main.java,在独立练习目录执行 javac -encoding UTF-8 Main.java,再执行 java Main。每章独立运行,不把多个public Main类放进同一文件。
import java.util.*;
public class Main {
public static void main(String[] args) {
String[] rows = {"Python;25", "SQL;20", "Python;35", "Java;bad", "SQL;-5", ";10"};
Map<String, Long> totals = new TreeMap<>();
List<Integer> rejected = new ArrayList<>();
for (int i = 0; i < rows.length; i++) {
String[] cells = rows[i].split(";", -1);
try {
if (cells.length != 2 || cells[0].isBlank()) throw new IllegalArgumentException();
int minutes = Integer.parseInt(cells[1].trim());
if (minutes < 0 || minutes > 240) throw new IllegalArgumentException();
totals.merge(cells[0].trim(), (long) minutes, Long::sum);
} catch (IllegalArgumentException e) { rejected.add(i + 1); }
}
totals.forEach((name, minutes) -> System.out.println(name + ": " + minutes));
System.out.println("Rejected lines: " + rejected);
}
}
推演与验证
Python合计60,SQL合计20;第4行非整数,第5行负数,第6行无课名,错误行号为[4, 5, 6]。
常见错误与边界
课程名目前区分大小写,Python与python是不同键。若要统一,需要先明确产品规则,再在累计之前标准化。
动手练习
追加"Java;0"与"Python;240",验证零和上界都可接受,再尝试"SQL;241"。
参考解法与理由
Java总计0、Python300、SQL20;新增第9行被拒绝。不要因分钟数为0而删除合法课程记录。