Java程序设计实践
Java训练集7~12总结与心得
训练集链接
前言: 训练集7~12主要巩固了面向对象基础的继承、多态、接口等内容,考察了面向对象进阶的相关知识点,如覆盖,常用的容器。题目的综合性较强,难度适中。
目录:
- 设计与分析
- 踩坑心得
- 改进建议
- 总结
设计与分析
1.课程成绩统计程序-1
某高校课程从性质上分为:必修课、选修课,从考核方式上分为:考试、考察。
考试的总成绩由平时成绩、期末成绩分别乘以权重值得出,比如平时成绩权重0.3,期末成绩权重0.7,总成绩=平时成绩0.3+期末成绩0.7。
考察的总成绩直接等于期末成绩
必修课的考核方式必须为考试,选修课可以选择考试、考察任一考核方式。
1、输入:
包括课程、课程成绩两类信息。
课程信息包括:课程名称、课程性质、考核方式(可选,如果性质是必修课,考核方式可以没有)三个数据项。
课程信息格式:课程名称+英文空格+课程性质+英文空格+考核方式
课程性质输入项:必修、选修
考核方式输入选项:考试、考察
课程成绩信息包括:学号、姓名、课程名称、平时成绩(可选)、期末成绩
课程信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+平时成绩+英文空格+期末成绩
以上信息的相关约束:
1)平时成绩和期末成绩的权重默认为0.3、0.7
2)成绩是整数,不包含小数部分,成绩的取值范围是【0,100】
3)学号由8位数字组成
4)姓名不超过10个字符
5)课程名称不超过10个字符
6)不特别输入班级信息,班级号是学号的前6位。
2、输出:
输出包含三个部分,包括学生所有课程总成绩的平均分、单门课程成绩平均分、单门课程总成绩平均分、班级所有课程总成绩平均分。
为避免误差,平均分的计算方法为累加所有符合条件的单个成绩,最后除以总数。
1)学生课程总成绩平均分按学号由低到高排序输出
格式:学号+英文空格+姓名+英文空格+总成绩平均分
如果某个学生没有任何成绩信息,输出:学号+英文空格+姓名+英文空格+"did not take any exams"
2)单门课程成绩平均分分为三个分值:平时成绩平均分(可选)、期末考试平均分、总成绩平均分,按课程名称的字符顺序输出
格式:课程名称+英文空格+平时成绩平均分+英文空格+期末考试平均分+英文空格+总成绩平均分
如果某门课程没有任何成绩信息,输出:课程名称+英文空格+"has no grades yet"
3)班级所有课程总成绩平均分按班级由低到高排序输出
格式:班级号+英文空格+总成绩平均分
如果某个班级没有任何成绩信息,输出:班级名称+英文空格+ "has no grades yet"
异常情况:
1)如果解析某个成绩信息时,课程名称不在已输入的课程列表中,输出:学号+英文空格+姓名+英文空格+":"+课程名称+英文空格+"does not exist"
2)如果解析某个成绩信息时,输入的成绩数量和课程的考核方式不匹配,输出:学号+英文空格+姓名+英文空格+": access mode mismatch"
以上两种情况如果同时出现,按第一种情况输出结果。
3)如果解析某个课程信息时,输入的课程性质和课程的考核方式不匹配,输出:课程名称+" : course type & access mode mismatch"
4)格式错误以及其他信息异常如成绩超出范围等,均按格式错误处理,输出"wrong format"
5)若出现重复的课程/成绩信息,只保留第一个课程信息,忽略后面输入的。
信息约束:
1)成绩平均分只取整数部分,小数部分丢弃
参考类图:
思路剖析:
- 先粗略看一遍题目,理解一下它给出的类图的作用
- 从类图中我们不难发现 选课事件是整个课程系统的中心,通过记录所有选课事件,可以得到每次course,student,score.
- 分析题目输出要求:1.每个学生的平均分。2.每门课程的平时平均分(有的要有的不要),每门课程的期末平时分。3.每个班的平均分
且输出需要按照规则排序。 - 根据输出要求,我们不难发现,需要单独使用容器记录下分值,又由于需要排序,所以我们可以直接使用多个treeMap来存储各类信息,例如存储学生的平均分,则代码如下:
TreeMap<Student,Integer>studentAverageScore=new TreeMap<Student,Integer>();
- 现在就可以开始写各种类了
- Student 类 属性是id,name。
- Score 类 为抽象类,由ExamScore,ExamineScore继承,其中分别重写getGrade()方法
- Course 类 属性是 type,name.
- CourseSelect 类 属性是 student grade course
- 接下来就要考虑细节部分了,这道题的细节非常多,我们从题目重新开始捋一遍
- 必修只能选考试,所以需要特判输入的成绩数量以及考核方式
- 选修课成绩信息可以只有期末分,不需要输入平时分,此处的变化导致最后输出课程平均分时将有相应变化
- 班级号由学号前6位组成,意味着需要用hashMap记录每个人的前6位学号,抽成班级集合。
- 最重要的细节在于何时加入课程或学生信息,何时不加,其中的关键就是 wrong format和其它异常的区别,只要是wrong format 就直接跳到下个循环,如果是其它异常,得分情况考虑是否要加入课程、学生信息。
- 课程信息不是简单的按照ASCII码排序,而是按照中文拼音进行排序,所以得重写排序规则,如下:
public int compareTo(Course o) { return Collator.getInstance(Locale.CHINA).compare(this.name, o.name); }
整体思路结束,现在看代码:
import java.util.*;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Locale;
import java.util.Objects;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
HashSet<CourseSelection> courseSelectionHashSet = new HashSet<>();
HashSet<String> courseNameSet = new HashSet<>();
HashMap<Student, Boolean> studentScorehashMap = new HashMap<>();
TreeMap<Student, Integer> averageStudentScore = new TreeMap<>();
TreeMap<Course, Integer> courseUsualAverage = new TreeMap<>();
TreeMap<Course, Integer> courseFinalAverage = new TreeMap<>();
TreeMap<Course, Integer> courseCombinedAverage = new TreeMap<>();
TreeMap<String, Integer> classCombinedAverage = new TreeMap<>();
StringBuilder stringBuilder = new StringBuilder();
while (true) {
String temp = scanner.nextLine();
if (temp.equals("end")) {
break;
}
String[] s = temp.split(" ");
if (s[0].matches("[0-9]{0,100}")) {
Student student = new Student(s[0], s[1]);
Course course = null;
if (s[0].length() != 8 || s[1].length() > 10 || s[2].length() > 10 || !s[3].matches("[0-9]{1,3}") || (Integer.parseInt(s[3]) < 0 || Integer.parseInt(s[3]) > 100)) {
System.out.println("wrong format");
continue;
}
if (courseNameSet.contains(s[2])) {
for (Course tempCourse : courseUsualAverage.keySet()) {
if (tempCourse.name.equals(s[2])) {
course = tempCourse;
break;
}
}
}
if (s.length == 5 && ((Integer.parseInt(s[4]) < 0) || (Integer.parseInt(s[4]) > 100))) {
System.out.println("wrong format");
continue;
} else if(course!=null&&course.mode==2){
if (!s[3].matches("[4-9]")) {
System.out.println("wrong format");
continue;
}
int flag=0;
for (int i = 4; i < s.length; i++) {
if (!s[i].matches("[0-9]{1,3}")) {
System.out.println("wrong format");
flag=1;
break;
} else if (Integer.parseInt(s[i]) < 0 || Integer.parseInt(s[i]) > 100) {
System.out.println("wrong format");
flag=1;
break;
}
}
if(flag==1)
continue;
if (s.length != Integer.parseInt(s[3]) + 4) {
System.out.println(s[0] + " " + s[1] + " " + ": access mode mismatch");
classCombinedAverage.put(s[0].substring(0, 6), 0);
averageStudentScore.put(student, 0);
continue;
}
}
if(!courseNameSet.contains(s[2])) {
System.out.println(s[2] + " does not exist");
averageStudentScore.put(student, 0);
classCombinedAverage.put(s[0].substring(0, 6), 0);
continue;
}
Grade grade = new ExamScore();
if (s.length == 4 && course.mode == 1) {
grade = new ExamineGrade();
grade.finalGrade = Integer.parseInt(s[3]);
} else if (s.length == 5 && course.mode == 0) {
grade = new ExamScore();
grade.usualGrade = Integer.parseInt(s[3]);
grade.finalGrade = Integer.parseInt(s[4]);
} else if (course.mode == 2) {
grade = new ExperimentalScore();
for (int i = 4; i < s.length; i++) {
grade.experimentalGrades.add(Integer.parseInt(s[i]));
}
}
classCombinedAverage.put(s[0].substring(0, 6), 0);
if ((s.length == 4 && course.mode == 0) || (s.length == 5 && course.mode == 1)) {
System.out.println(s[0] + " " + s[1] + " " + ": access mode mismatch");
averageStudentScore.put(student, 0);
continue;
}
//获取每个同学,以便计算平均分
averageStudentScore.put(student, 0);
CourseSelection courseSelection = new CourseSelection(course, student, grade);
courseSelectionHashSet.add(courseSelection);
} else {
if (s.length != 3 && s.length != 2) {
System.out.println("wrong format");
continue;
}
if ((s.length == 3) && (s[0].length() > 10 || ((!s[1].equals("必修") && !s[1].equals("选修") && !s[1].equals("实验")) || (!s[2].equals("考试") && !s[2].equals("考察") && !s[2].equals("实验"))))) {
System.out.println("wrong format");
continue;
} else if ((s.length == 2) && (s[0].length() > 10 || !s[1].equals("必修"))) {
System.out.println("wrong format");
continue;
}
int type = 0;
if (s[1].equals("必修")) type = 0;
if (s[1].equals("选修")) type = 1;
if (s[1].equals("实验")) type = 2;
Course course = new Course(s[0], type);
if (s.length == 3) {
int mode = 0;
if (s[2].equals("考试")) mode = 0;
if (s[2].equals("考察")) mode = 1;
if (s[2].equals("实验")) mode = 2;
course.mode = mode;
}
if ((course.type == 0 && course.mode == 1) || (course.mode == 2 && course.type != 2) || course.type == 2 && course.mode != 2) {
System.out.println(s[0] + " : course type & access mode mismatch");
continue;
}
courseUsualAverage.put(course, 0);
courseFinalAverage.put(course, 0);
courseCombinedAverage.put(course, 0);
courseNameSet.add(s[0]);
}
}
//courseSelectionHashSet.stream().map(s->s.course.name).forEach(System.out::println);
//1.求每个同学平均成绩,排序打印
for (Student student : averageStudentScore.keySet()) {
List<Integer> list = new ArrayList<>();
for (CourseSelection courseSelection : courseSelectionHashSet) {
if (courseSelection.student.id.equals(student.id)) {
list.add(courseSelection.grade.getGrade());
}
}
//List<Integer> list = courseSelectionHashSet.stream().filter(s -> s.student.id.equals(student.id)).map(s -> s.grade.getGrade()).toList();
for (Integer tempScore : list) {
averageStudentScore.replace(student, averageStudentScore.get(student) + tempScore);
}
if (list.size() != 0)
averageStudentScore.replace(student, averageStudentScore.get(student) / list.size());
if (list.size() == 0) {
studentScorehashMap.put(student, false);
System.out.println(student.id + " " + student.name + " " + "did not take any exams");
} else {
studentScorehashMap.put(student, true);
System.out.println(student.id + " " + student.name + " " + averageStudentScore.get(student));
}
}
//2.计算每门课程的平均 平时分,期末分,综合分
for (Course course : courseUsualAverage.keySet()) {
List<Integer> list = new ArrayList<>();
List<Integer> list1 = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();
//平时分
for (CourseSelection courseSelection : courseSelectionHashSet) {
if (courseSelection.course.name.equals(course.name)) {
list.add(courseSelection.grade.usualGrade);
}
}
//list = courseSelectionHashSet.stream().filter(s -> s.course.name.equals(course.name)).map(s -> s.grade.usualGrade).toList();
//期末分
for (CourseSelection courseSelection : courseSelectionHashSet) {
if (courseSelection.course.name.equals(course.name)) {
list1.add(courseSelection.grade.finalGrade);
}
}
//list1 = courseSelectionHashSet.stream().filter(s -> s.course.name.equals(course.name)).map(s -> s.grade.finalGrade).toList();
//综合分
for (CourseSelection courseSelection : courseSelectionHashSet) {
if (courseSelection.course.name.equals(course.name)) {
list2.add(courseSelection.grade.getGrade());
}
}
//list2 = courseSelectionHashSet.stream().filter(s -> s.course.name.equals(course.name)).map(s -> s.grade.getGrade()).toList();
for (Integer tempScore : list) {
courseUsualAverage.replace(course, courseUsualAverage.get(course) + tempScore);
}
for (Integer tempScore : list1) {
courseFinalAverage.replace(course, courseFinalAverage.get(course) + tempScore);
}
for (Integer tempScore : list2) {
courseCombinedAverage.replace(course, courseCombinedAverage.get(course) + tempScore);
}
if (list.size() != 0)
courseUsualAverage.replace(course, courseUsualAverage.get(course) / list.size());
if (list1.size() != 0)
courseFinalAverage.replace(course, courseFinalAverage.get(course) / list1.size());
if (list2.size() != 0)
courseCombinedAverage.replace(course, courseCombinedAverage.get(course) / list2.size());
if (list.size() == 0) {
System.out.println(course.name + " has no grades yet");
} else {
if (course.mode == 0)
System.out.println(course.name + " " + courseUsualAverage.get(course) + " " + courseFinalAverage.get(course) + " " + courseCombinedAverage.get(course));
else if(course.mode!=2)
System.out.println(course.name + " " + courseFinalAverage.get(course) + " " + courseCombinedAverage.get(course));
else
System.out.println(course.name +" "+ courseCombinedAverage.get(course));
}
}
//3.计算班级的分数
for (String classId : classCombinedAverage.keySet()) {
int sum = 0;//人数
boolean flag = false;//班级是否有分数记录
for (Student student : averageStudentScore.keySet()) {
if (student.id.substring(0, 6).equals(classId)) {
classCombinedAverage.replace(classId, classCombinedAverage.get(classId) + averageStudentScore.get(student));
if (studentScorehashMap.get(student)) {
flag = true;
sum++;
}
}
}
if (sum != 0)
classCombinedAverage.replace(classId, classCombinedAverage.get(classId) / sum);
if (flag) {
System.out.println(classId + " " + classCombinedAverage.get(classId));
} else {
System.out.println(classId + " " + "has no grades yet");
}
}
}
}
class Course implements Comparable<Course>{
protected String name;
protected int type;//0为必修,1为选修,2为实验
protected int mode=0;//0为考试,1为考察,2为实验
public Course(String name, int type, int mode) {
this.name = name;
this.type = type;
this.mode = mode;
}
public Course(String name){
this.name=name ;
};
public Course(String name,int type){
this.name=name;
this.type=type;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Course course = (Course) o;
return Objects.equals(name, course.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
@Override
public int compareTo(Course o) {
return Collator.getInstance(Locale.CHINA).compare(this.name, o.name);
}
}
class CourseSelection {
protected Course course;
protected Student student;
protected Grade grade;
public CourseSelection(Course course, Student student, Grade grade) {
this.course = course;
this.student = student;
this.grade = grade;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CourseSelection that = (CourseSelection) o;
return Objects.equals(course, that.course) && Objects.equals(student, that.student);
}
@Override
public int hashCode() {
return Objects.hash(course, student);
}
}
class ExamineGrade extends Grade{
@Override
Integer getGrade() {
return this.finalGrade;
}
public ExamineGrade(){
type=1;
}
}
class ExamScore extends Grade{
@Override
Integer getGrade() {
return (int)( this.usualGrade*0.3+this.finalGrade*0.7);
}
public ExamScore(){
type=0;
}
}
class ExperimentalScore extends Grade{
Integer getGrade(){
Integer result=0;
for(Integer integer:experimentalGrades){
result+=integer;
}
return result/experimentalGrades.size();
}
}
abstract class Grade {
protected Integer finalGrade=0;
protected int type;
protected Integer usualGrade=0;
protected ArrayList<Integer>experimentalGrades=new ArrayList<>();
abstract Integer getGrade();
}
class Student implements Comparable<Student>{
protected String id;
protected String name;
public Student() {
}
public Student(String id, String name) {
this.id = id;
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return Objects.equals(id, student.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@Override
public int compareTo(Student s) {
return this.id.compareTo(s.id);
}
}
2.课程成绩统计程序-2
课程成绩统计程序-2在第一次的基础上增加了实验课
某高校课程从性质上分为:必修课、选修课、实验课,从考核方式上分为:考试、考察、实验。
实验的总成绩等于课程每次实验成绩的平均分
必修课的考核方式必须为考试,选修课可以选择考试、考察任一考核方式。实验课的成绩必须为实验。
课程性质输入项:必修、选修、实验
考核方式输入选项:考试、考察、实验
实验课程成绩信息包括:学号、姓名、课程名称、实验次数、每次成绩
实验次数至少4次,不超过9次
实验课程信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+实验次数+英文空格+第一次实验成绩+...+英文空格+最后一次实验成绩
实验课成绩格式:课程名称+英文空格+总成绩平均分
思路分析:
- 根据题意,加入了实验课,意味着course的type属性要有3个值,且course要新增一个属性mode,记录考核方式
- 加一个实验成绩类,ExperimentScore,继承Score,Score中要增加ArrayList已记录每一次实验成绩,ExperimentScore类要重写getGrade方法
- 题目中的各种信息范围进行进一步特判
主要修改的代码如下:
class ExperimentalScore extends Grade{
Integer getGrade(){
Integer result=0;
for(Integer integer:experimentalGrades){
result+=integer;
}
return result/experimentalGrades.size();
}
}
abstract class Grade {
protected Integer finalGrade=0;
protected int type;
protected Integer usualGrade=0;
protected ArrayList<Integer>experimentalGrades=new ArrayList<>();
abstract Integer getGrade();
}
class Course implements Comparable<Course>{
protected String name;
protected int type;//0为必修,1为选修,2为实验
protected int mode=0;//0为考试,1为考察,2为实验
public Course(String name, int type, int mode) {
this.name = name;
this.type = type;
this.mode = mode;
}
public Course(String name){
this.name=name ;
};
public Course(String name,int type){
this.name=name;
this.type=type;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Course course = (Course) o;
return Objects.equals(name, course.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
@Override
public int compareTo(Course o) {
return Collator.getInstance(Locale.CHINA).compare(this.name, o.name);
}
}
3.课程成绩统计程序-3
课程成绩统计程序-3在第二次的基础上修改了计算总成绩的方式
要求:修改类结构,将成绩类的继承关系改为组合关系,成绩信息由课程成绩类和分项成绩类组成,课程成绩类组合分项成绩类,分项成绩类由成绩分值和权重两个属性构成。
完成课程成绩统计程序-2、3两次程序后,比较继承和组合关系的区别。思考一下哪一种关系运用上更灵活,更能够适应变更。
题目最后的参考类图未做修改,大家根据要求自行调整,以下内容加粗字体显示的内容为本次新增的内容。
考试的总成绩由平时成绩、期末成绩分别乘以权重值得出,比如平时成绩权重0.3,期末成绩权重0.7,总成绩=平时成绩*0.3+期末成绩*0.7。
实验的总成绩等于课程每次实验成绩乘以权重后累加而得。
课程权重值在录入课程信息时输入。(注意:所有分项成绩的权重之和应当等于1)
课程信息包括:课程名称、课程性质、考核方式、分项成绩数量、每个分项成绩的权重。
考试课信息格式:课程名称+英文空格+课程性质+英文空格+考核方式+英文空格+平时成绩的权重+英文空格+期末成绩的权重
考察课信息格式:课程名称+英文空格+课程性质+英文空格+考核方式
实验课程信息格式:课程名称+英文空格+课程性质+英文空格+考核方式+英文空格+分项成绩数量n+英文空格+分项成绩1的权重+英文空格+。。。+英文空格+分项成绩n的权重
实验课程成绩信息包括:学号、姓名、课程名称、每次成绩{在系列-2的基础上去掉了(实验次数),实验次数要和实验课程信息中输入的分项成绩数量保持一致}
为避免四舍五入误差,
计算单个成绩时,分项成绩乘以权重后要保留小数位,计算总成绩时,累加所有分项成绩的权重分以后,再去掉小数位。
学生总成绩/整个班/课程平均分的计算方法为累加所有符合条件的单个成绩,最后除以总数。
单门课程成绩按课程名称的字符顺序输出
课程成绩输出格式:课程名称+英文空格+总成绩平均分
如果解析实验课程信息时,输入的分项成绩数量值和分项成绩权重的个数不匹配,输出:课程名称+" : number of scores does not match"
如果解析考试课、实验课时,分项成绩权重值的总和不等于1,输出:课程名称+" : weight value error"
思路分析:
- 权重自定义,所以Score类需要大改,且实验课每次实验成绩的权重都要自定义,所以自定义的权重可共用一个ArrayList,作为Score的属性
- 课程信息与系列2中的课程信息不一样,这里的实验课课程信息包含实验次数,而实验课成绩信息不包含次数,所以输入和输出的判断要修改一下。
- 细节:
- 权重的判断中,要判断是否和为1,由于精度问题,需要取定范围,如-0.01到0.01。
- 这道题所有需要用到浮点数的地方全要写float,不能用double测试点需要这样通过。
类图如下:
修改后的代码如下:
import java.util.*;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Locale;
import java.util.Objects;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
HashSet<CourseSelection> courseSelectionHashSet = new HashSet<>();
HashSet<String> courseNameSet = new HashSet<>();
HashMap<Student, Boolean> studentScorehashMap = new HashMap<>();
TreeMap<Student, Integer> averageStudentScore = new TreeMap<>();
TreeMap<Course, Integer> courseUsualAverage = new TreeMap<>();
TreeMap<Course, Integer> courseFinalAverage = new TreeMap<>();
TreeMap<Course, Integer> courseCombinedAverage = new TreeMap<>();
TreeMap<String, Integer> classCombinedAverage = new TreeMap<>();
TreeMap<Course, ArrayList<Float>> scoreWeight = new TreeMap<>();
StringBuilder stringBuilder = new StringBuilder();
while (true) {
String temp = scanner.nextLine();
if (temp.equals("end")) {
break;
}
String[] s = temp.split(" ");
if (s[0].matches("[0-9]{0,100}")) {
Student student = new Student(s[0], s[1]);
Course course = null;
Grade grade = new ExamScore();
ArrayList<Float>weight=new ArrayList<>();
if (s.length >= 5) {
int flag = 0;
for (int i = 4; i < s.length; i++) {
if (!s[i].matches("[0-9]{1,3}")) {
System.out.println("wrong format");
flag = 1;
break;
} else if (Integer.parseInt(s[i]) < 0 || Integer.parseInt(s[i]) > 100) {
System.out.println("wrong format");
flag = 1;
break;
}
}
if (flag == 1)
continue;
}
if (s[0].length() != 8 || s[1].length() > 10 || s[2].length() > 10 || !s[3].matches("[0-9]{1,3}") || (Integer.parseInt(s[3]) < 0 || Integer.parseInt(s[3]) > 100)) {
System.out.println("wrong format");
continue;
}
if (courseNameSet.contains(s[2])) {
for (Course tempCourse : courseUsualAverage.keySet()) {
if (tempCourse.name.equals(s[2])) {
grade.weight = scoreWeight.get(tempCourse);
weight=grade.weight;
course = tempCourse;
break;
}
}
}
if (s.length == 5 && ((Integer.parseInt(s[4]) < 0) || (Integer.parseInt(s[4]) > 100))) {
System.out.println("wrong format");
continue;
} else if (course != null && course.mode == 2) {
if(course.mode!=2&&s.length>5){
System.out.println("wrong format");
continue;
}
if (s.length != grade.weight.size() + 3) {
System.out.println(s[0] + " " + s[1] + " " + ": access mode mismatch");
classCombinedAverage.put(s[0].substring(0, 6), 0);
averageStudentScore.put(student, 0);
continue;
}
}
if (!courseNameSet.contains(s[2])) {
System.out.println(s[2] + " does not exist");
averageStudentScore.put(student, 0);
classCombinedAverage.put(s[0].substring(0, 6), 0);
continue;
}
if (s.length == 4 && course.mode == 1) {
grade = new ExamineGrade();
grade.weight=weight;
grade.finalGrade = Integer.parseInt(s[3]);
} else if (s.length == 5 && course.mode == 0) {
grade = new ExamScore();
grade.weight=weight;
grade.usualGrade = Integer.parseInt(s[3]);
grade.finalGrade = Integer.parseInt(s[4]);
} else if (course.mode == 2) {
grade = new ExperimentalScore();
grade.weight=weight;
for (int i = 3; i < s.length; i++) {
grade.experimentalGrades.add(Integer.parseInt(s[i]));
}
}
classCombinedAverage.put(s[0].substring(0, 6), 0);
if ((s.length != 5 && course.mode == 0) || (s.length != 4 && course.mode == 1)) {
System.out.println(s[0] + " " + s[1] + " " + ": access mode mismatch");
averageStudentScore.put(student, 0);
continue;
}
//获取每个同学,以便计算平均分
averageStudentScore.put(student, 0);
CourseSelection courseSelection = new CourseSelection(course, student, grade);
courseSelectionHashSet.add(courseSelection);
} else {
if(s.length>=5&&s[2].equals("考试")&&(!s[3].matches("0\\.[0-9]{1,2}")||!s[4].matches("0\\.[0-9]{1,2}"))){
System.out.println("wrong format");
continue;
}
if ((s[0].length() > 10 || ((!s[1].equals("必修") && !s[1].equals("选修") && !s[1].equals("实验")) || (!s[2].equals("考试") && !s[2].equals("考察") && !s[2].equals("实验"))))) {
System.out.println("wrong format");
continue;
} else if ((s.length == 2) && (s[0].length() > 10 || !s[1].equals("必修"))) {
System.out.println("wrong format");
continue;
}
int type = 0;
ArrayList<Float> arrayList = new ArrayList<>();
if (s[1].equals("必修")) type = 0;
if (s[1].equals("选修")) type = 1;
if (s[1].equals("实验")) type = 2;
Course course = new Course(s[0], type);
int mode = 0;
if (s[2].equals("考试")) mode = 0;
if (s[2].equals("考察")) mode = 1;
if (s[2].equals("实验")) mode = 2;
course.mode = mode;
if ((course.type == 0 && course.mode == 1) || (course.mode == 2 && course.type != 2) || course.type == 2 && course.mode != 2) {
System.out.println(s[0] + " : course type & access mode mismatch");
continue;
}
if (s[1].equals("实验") && !s[3].matches("[4-9]")) {
System.out.println("wrong format");
continue;
} else if (s[1].equals("实验") && Integer.parseInt(s[3]) + 4 != s.length) {
System.out.println(course.name + " : number of scores does not match");
continue;
} else if ((s[2].equals("考试"))&&(Math.abs (Float.parseFloat(s[3])+Float.parseFloat(s[4])- 1)>0.01)) {
System.out.println(course.name + " : weight value error");
continue;
} else if (s[1].equals("实验")) {
int n = Integer.parseInt(s[3]);
float sum = 0;
for (int i = 0; i < n; i++) {
float tempFloat = Float.parseFloat(s[i + 4]);
sum += tempFloat;
arrayList.add(tempFloat);
}
if (Math.abs(sum-1)>0.01) {
System.out.println(course.name + " : weight value error");
continue;
}
} else if (s[2].equals("考试")) {
arrayList.add(Float.parseFloat(s[3]));
arrayList.add(Float.parseFloat(s[4]));
}
if(courseNameSet.contains(course.name)){
continue;
}
scoreWeight.put(course, arrayList);
courseUsualAverage.put(course, 0);
courseFinalAverage.put(course, 0);
courseCombinedAverage.put(course, 0);
courseNameSet.add(s[0]);
}
}
//courseSelectionHashSet.stream().map(s->s.course.name).forEach(System.out::println);
//1.求每个同学平均成绩,排序打印
for (Student student : averageStudentScore.keySet()) {
List<Integer> list = new ArrayList<>();
for (CourseSelection courseSelection : courseSelectionHashSet) {
if (courseSelection.student.id.equals(student.id)) {
list.add(courseSelection.grade.getGrade());
}
}
//List<Integer> list = courseSelectionHashSet.stream().filter(s -> s.student.id.equals(student.id)).map(s -> s.grade.getGrade()).toList();
for (Integer tempScore : list) {
averageStudentScore.replace(student, averageStudentScore.get(student) + tempScore);
}
if (list.size() != 0)
averageStudentScore.replace(student, averageStudentScore.get(student) / list.size());
if (list.size() == 0) {
studentScorehashMap.put(student, false);
System.out.println(student.id + " " + student.name + " " + "did not take any exams");
} else {
studentScorehashMap.put(student, true);
System.out.println(student.id + " " + student.name + " " + averageStudentScore.get(student));
}
}
//2.计算每门课程的平均 平时分,期末分,综合分
for (Course course : courseUsualAverage.keySet()) {
List<Integer> list = new ArrayList<>();
List<Integer> list1 = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();
//平时分
for (CourseSelection courseSelection : courseSelectionHashSet) {
if (courseSelection.course.name.equals(course.name)) {
list.add(courseSelection.grade.usualGrade);
}
}
//list = courseSelectionHashSet.stream().filter(s -> s.course.name.equals(course.name)).map(s -> s.grade.usualGrade).toList();
//期末分
for (CourseSelection courseSelection : courseSelectionHashSet) {
if (courseSelection.course.name.equals(course.name)) {
list1.add(courseSelection.grade.finalGrade);
}
}
//list1 = courseSelectionHashSet.stream().filter(s -> s.course.name.equals(course.name)).map(s -> s.grade.finalGrade).toList();
//综合分
for (CourseSelection courseSelection : courseSelectionHashSet) {
if (courseSelection.course.name.equals(course.name)) {
list2.add(courseSelection.grade.getGrade());
}
}
//list2 = courseSelectionHashSet.stream().filter(s -> s.course.name.equals(course.name)).map(s -> s.grade.getGrade()).toList();
for (Integer tempScore : list) {
courseUsualAverage.replace(course, courseUsualAverage.get(course) + tempScore);
}
for (Integer tempScore : list1) {
courseFinalAverage.replace(course, courseFinalAverage.get(course) + tempScore);
}
for (Integer tempScore : list2) {
courseCombinedAverage.replace(course, courseCombinedAverage.get(course) + tempScore);
}
if (list.size() != 0)
courseUsualAverage.replace(course, courseUsualAverage.get(course) / list.size());
if (list1.size() != 0)
courseFinalAverage.replace(course, courseFinalAverage.get(course) / list1.size());
if (list2.size() != 0)
courseCombinedAverage.replace(course, courseCombinedAverage.get(course) / list2.size());
if (list.size() == 0) {
System.out.println(course.name + " has no grades yet");
} else {
System.out.println(course.name + " " + courseCombinedAverage.get(course));
}
}
//3.计算班级的分数
for (String classId : classCombinedAverage.keySet()) {
int sum = 0;//人数
boolean flag = false;//班级是否有分数记录
for (Student student : averageStudentScore.keySet()) {
if (student.id.substring(0, 6).equals(classId)) {
classCombinedAverage.replace(classId, classCombinedAverage.get(classId) + averageStudentScore.get(student));
if (studentScorehashMap.get(student)) {
flag = true;
sum++;
}
}
}
if (sum != 0)
classCombinedAverage.replace(classId, classCombinedAverage.get(classId) / sum);
if (flag) {
System.out.println(classId + " " + classCombinedAverage.get(classId));
} else {
System.out.println(classId + " " + "has no grades yet");
}
}
}
}
class Course implements Comparable<Course>{
protected String name;
protected int type;//0为必修,1为选修,2为实验
protected int mode=0;//0为考试,1为考察,2为实验
public Course(String name, int type, int mode) {
this.name = name;
this.type = type;
this.mode = mode;
}
public Course(String name){
this.name=name ;
};
public Course(String name,int type){
this.name=name;
this.type=type;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Course course = (Course) o;
return Objects.equals(name, course.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
@Override
public int compareTo(Course o) {
return Collator.getInstance(Locale.CHINA).compare(this.name, o.name);
}
}
class CourseSelection {
protected Course course;
protected Student student;
protected Grade grade;
public CourseSelection(Course course, Student student, Grade grade) {
this.course = course;
this.student = student;
this.grade = grade;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CourseSelection that = (CourseSelection) o;
return Objects.equals(course, that.course) && Objects.equals(student, that.student);
}
@Override
public int hashCode() {
return Objects.hash(course, student);
}
}
class ExamineGrade extends Grade{
@Override
Integer getGrade() {
return this.finalGrade;
}
public ExamineGrade(){
type=1;
}
}
class ExamScore extends Grade{
@Override
Integer getGrade() {
if(weight.size()!=0)
return (int)( this.usualGrade* weight.get(0)+this.finalGrade*weight.get(1));
return (int)( this.usualGrade* 0.3+this.finalGrade*0.7);
}
public ExamScore(){
type=0;
}
}
class ExperimentalScore extends Grade{
Integer getGrade(){
float result=0;
for(int i=0;i<experimentalGrades.size();i++){
result+=experimentalGrades.get(i)* weight.get(i);
}
return (int)result;
}
}
abstract class Grade {
protected Integer finalGrade=0;
protected int type;
protected Integer usualGrade=0;
protected ArrayList<Integer>experimentalGrades=new ArrayList<>();
protected ArrayList<Float>weight=new ArrayList<>();
abstract Integer getGrade();
}
class Student implements Comparable<Student>{
protected String id;
protected String name;
public Student() {
}
public Student(String id, String name) {
this.id = id;
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return Objects.equals(id, student.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@Override
public int compareTo(Student s) {
return this.id.compareTo(s.id);
}
}
踩坑心得
- 万万不能直接用Integer.parseInt(),如果括号中是一段文字,那就会直接报错非零返回,所以使用前要判断字符串,使用matches()方法检测是否是数字
- 平时分在计算时,有的选修课没有平时分,所以sum=0;在计算平均分的时候就会除以sum,报错。这个地方需要特判课程考核类型
- 浮点数相加会有精度误差,需要设置误差范围(典型例题就是等腰直角三角形)
- treeMap是会对键进行排序的,所以自定义键类需要重写compareTo方法以满足需求。
改进建议
- 如上代码,关于成绩信息与课程信息分类的方面,我的代码是一股脑直接分的,会降低可读性,这里最好在Main类中封装一个方法专门对两类信息进行分类
- 计算考试成绩,考察成绩,移入成绩ArrayList的话会更好,这样三门课程统一使用权重列表,分数列表进行计算,减少了不必要的额外思考。
总结
收获:
- 巩固了面向对象的基础知识,如继承、多态和接口。
- 学习了进阶的面向对象概念,如覆盖和常用的容器。
- 通过实践和练习,提高了代码的可读性、可维护性和复用性。
需要进一步学习的地方:
学习方向:
- 深入理解和应用设计原则和模式:我希望进一步学习和实践各种设计原则和模式,以便在实际项目中能够更好地设计和组织代码结构。
- 扩展应用场景:除了课程中提到的基本应用场景,我希望了解更多面向对象编程在不同领域中的应用,例如Web开发、数据科学和人工智能等领域。
- 深入学习语言特性和工具库:为了更好地使用面向对象编程,我计划进一步学习编程语言的高级特性和相关的工具库,以便更加高效地开发和解决问题。
对Java程序设计课的感受与建议
- 关于教学理念(OBE):我认为需要进一步明确学习成果的具体内容和评估方式,以确保学生能够真正掌握和应用所学的知识和技能。
- 关于教学方法(边讲边练):其实很大程度上学生都是自学,所以讲的部分可以减少,练的难度可以增加
- 关于教学组织(线上线下混合式教学):可以更加深入的发掘线上平台的互动功能,促进学生之间和学生与教师之间的交流和合作。
- 关于教学过程(PTA题目集驱动):PTA题目集驱动的教学过程可以进一步增加开放性问题和案例分析的比重,以帮助学生更全面地思考和解决实际问题,培养独立思考和创新能力。
总体而言,以上是一些需要改进和加强的方面。通过改进教学理念的明确性、提高实践的难度和深度、衔接线上线下教学、增加开放性问题和案例分析、加强学生反馈和评估等,可以进一步提升java课程的教学质量和学生的学习效果。
标签:Java,name,实践,equals,course,mode,student,new,程序设计 From: https://www.cnblogs.com/AI-xiong/p/17501081.html