选修课-字符串哈希表排序

题目:现有两门选修课,每门选修课都有一部分学生选修,每个学生都有选修课的成绩,需要你找出同时选修了两门选修课的学生,先按照班级进行划分,班级编号小的先输出,每个班级按照两门选修课成绩和的降序排序,成绩相同时按照学生的学号升序排序。

学号+成绩组成,中间,分割;要求:1.选出同时选修两门课的学生2.先按班级划分,班级编号小的先输出3.每个班级按照两门修选课成绩和降序排列4.成绩相同按照学号的升序排序
学号组成:总共8位数=2院系编号+2入学年份后两位+1院系内部专业编号+3所在班级的学号,班级为学号的前5位

思路:

(1)先定义学生类,实现comparable接口,重写compareTo方法(2)定义学号和成绩两个字段(3)重写方法进行分数比较,分数大的排在前面;分数相同再进行学号比较,升序排列;学号相等,则第一个学生排在前面
(2)主类中:2.1先将每门课信息集合到数组里;2.2分离出学号进行对比;2.3如果同时选修了两门课,则计算总成绩,并将学生信息,总计加入到学生类;2.4最后加入到map中

public static void main(String[] args) {

    Scanner sc = new Scanner(System.in);

    String[] one = sc.nextLine().split(";");
    String[] two = sc.nextLine().split(";");

    Map<String, List<Student>> map = new HashMap<>();
    for(int i=0; i<one.length; i++){

        String[] oneStu = one[i].split(",");
        //学生学号
        String oneStuId = oneStu[0];

        for(int j=0; j<two.length; j++){

            String[] twoStu = two[j].split(",");
            //学生学号
            String twoStuId = twoStu[0];
            //同时选修两门课
            if(oneStuId.equals(twoStuId)){

                int oneStuScore = Integer.parseInt(oneStu[1]);
                int twoStuScore = Integer.parseInt(twoStu[1]);
                //总成绩
                int totalScore = oneStuScore + twoStuScore;
                //班级编号
                String cla = twoStuId.substring(0, 5);
                //学生信息
                Student student = new Student(oneStuId, totalScore);
                //如果有班级编号,则输入学生信息
                if(map.containsKey(cla)){
                    map.get(cla).add(student);
                }else {
                    //没有则将学生的班级编号和学生信息push进去
                    List<Student> list = new ArrayList<>();
                    list.add(student);
                    map.put(cla, list);
                }
            }
        }
    }

    if(map.size() == 0){
        //没有符合要求的
        System.out.println("NULL");
    }else {
        /**
         * 这行代码的作用是将 `map` 转换为一个 `List`,该 `List` 中的每个元素都是一个 `Map.Entry` 对象,其中包含了班级编号和对应的学生信息列表。
         * 解释如下:
         * `map.entrySet()` 方法返回一个 `Set<Map.Entry>`,该 `Set` 中包含了 `map` 中全部的键值对。而 `Map.Entry` 则是表示一个键值对的接口。
         * `ArrayList<>(map.entrySet())` 是将 `map.entrySet()` 返回的键值对集合转换成一个 `ArrayList` 对象,然后将其赋值给 `mapList` 变量。
         * 因此,`mapList` 变量就是一个包含了 `map` 中全部键值对的 `List` 对象,每个元素都是一个 `Map.Entry` 对象。
         * 这样处理之后,我们可以通过遍历 `mapList` 来访问 `map` 中的键值对,并对其进行排序或其他操作。
         * */
        List<Map.Entry<String, List<Student>>> mapList = new ArrayList<>(map.entrySet());
        /**
         *在这段代码中,返回-1和1是用来定义比较器的规则。比较器是用来对对象进行比较排序的工具。
         * 在这里,`mapList.sort()`的参数是一个Lambda表达式,用来比较两个键值对的键。如果第一个键(`a.getKey()`)小于第二个键(`b.getKey()`),则返回-1,表示第一个键应该排在前面;如果第一个键大于第二个键,则返回1,表示第一个键应该排在后面。这样可以通过对键进行排序,从而按照班级编号进行排序。
         * 在Java中,比较器返回负数表示第一个对象较小,返回正数表示第一个对象较大,返回0表示两个对象相等。
         * 总结起来,这段代码的作用是对 `mapList`(存储学生信息的列表)中的元素进行排序,按照班级编号进行升序排序。返回-1表示第一个元素应该排在前面,返回1表示第一个元素应该排在后面。
         * */
        mapList.sort((a,b) -> {
            if(a.getKey().compareTo(b.getKey()) < 0){
                return -1;
            }
            return 1;
        });

        for(Map.Entry<String, List<Student>> m : mapList){
            //输出班级编号
            System.out.println(m.getKey());
            String res = "";
            //对学生按照要求排序
            Collections.sort(m.getValue());
            for(Student s : m.getValue()){
                res += s.stuId + ";";
            }
            //再输出学号
            System.out.println(res.substring(0, res.length() - 1));
        }
    }

}

static class Student implements Comparable<Student> {

    String stuId;
    int score;

    public Student(String stuId, int score){
        this.stuId = stuId;
        this.score = score;
    }

    @Override
    public int compareTo(Student o) {
        if(this.score > o.score){
            return -1;
        }else if(this.score == o.score){
            if(this.stuId.compareTo(o.stuId) > 0){
                return 1;
            }
            return -1;
        }
        return 1;
    }
}
posted @ 2023-11-02 11:58  约拿小叶  阅读(4)  评论(0编辑  收藏  举报