上周我做了一个关于Java Set和Map类的讲座。这些类为我们提供了一种快速有效地存储和检索信息的方法。今天的示例程序将演示如何使用这些类来组织信息。具体来说,我们将构建一个程序来记录和管理班级中一组学生的数据。
问题的起点是一个包含一组学生测验分数的文件。该文件中的条目采用以下形式
<学生姓名> <测验编号> <测验分数>
下面是这个文件中一些典型的行:
D 1 61 C 4 77 L 4 99 I 2 94 K 7 95 B 3 66
因为学生按照自己的进度学习,并且在学生提交作业时记录测验分数,所以测验分数的顺序是不可预测的。
我们将构建的程序将根据文本文件中的数据打印两个报告。
为了构建我们的程序,我们需要构造两个类:一个是Student类,它记录每个学生的测验成绩,另一个是Roster类,它存储我们将要创建的赢博体育Student对象。
Student类的结构如下:
公共类学生{私有字符串名称;private TreeMap<Integer,Integer> grades;public Student(String name) {this.name = name;grade = new TreeMap<Integer,Integer ();}公共字符串getName(){返回名称;}公共无效recordGrade(int quiz,int grade){成绩。把(年级测试);}}
因为测验既有测验编号也有关联分数,所以我将把测验成绩存储在一个TreeMap中,该TreeMap使用测验编号作为键,并使用关联分数作为值。
名册类将有这样的结构:
public class Roster {private TreeMap<String,Student> Roster;private TreeSet<Integer> quiz;public Roster() {Roster = new TreeMap<String,Student>();quizzes = new TreeSet<Integer>();}}
成员变量名册存储学生对象。由于我们需要根据学生的姓名查找学生,因此花名册是一个映射,它使用学生的姓名作为键,并使用student对象作为值。
我还添加了第二个成员变量quizzes,我将使用它来跟踪哪些quizzes至少有一个学生提交了该测验。这将在稍后生成学生尚未提交的测验报告时非常有用。
下面是我们将添加到名册类的readScores()方法的代码。
公共无效readScores(字符串fileName){扫描器输入= null;try {input = new Scanner(new File(fileName));} catch(异常ex) {System.out。println(“无法打开文件”);system . exit (1);} while(input.hasNext()){字符串名称= input.next();int quiz = input.nextInt();int grade = input.nextInt();如果(! roster.containsKey(名称))名单。put(name, new Student(name));Student = name .get(name);st.recordGrade(年级测试);如果(! quizzes.contains(测验)quizzes.add(测试);} input.close ();}
while循环将读取文本文件中的各个行。每行将以一个学生的名字开始:我们需要检查的第一件事是是否为这个学生创建了一个student对象。如果没有,我们继续为这个学生创建一个新的Student对象,并把这个对象放到花名册中。然后,我们在花名册中查找学生,并告诉该学生对象为该测验记录一个分数。
每次我们读到一个提到特定测试数字的条目时,我们也会检查我们的测试中是否设置了该测试的数字。如果没有,我们将把测验号码添加到我们所看到的测验集中。
一旦我们将赢博体育数据加载到程序中,我们就可以打印这两个报告了。打印这些报告的第一步是向Student类添加方法,这些方法将允许Student计算当前测验的平均值,并打印他们尚未参加的测验列表。
public double quizAverage() {double sum = 0;For (int score: grades.values()) sum += score;返回总和/ grades.size ();}公共无效printMissing(TreeSet<Integer> quizzes, printwwriter out) {for(int n: quizzes) {if(!grades.containsKey(n)) out。Println (name + " " + n);}}
将这两个方法添加到Student类后,我们可以将方法添加到Roster类以生成我们需要的两个报告。
public void printMissingQuizzes() {printwwriter out = new printwwriter (System.out);for(Student st: roster.values()) st. printmissing (quizzes, out);out.close ();}公共无效printAverages() {for(学生st:罗斯特.values()) {System.out.print(st. getname () + ":");System.out.printf(“% .1f \ n”,st.quizAverage ());}}