如何在Java中按科目优先级及分数对学生列表排序并排名?
学生按科目优先级排序并计算排名解决方案
问题需求
- 根据给定的
subjectPriorityOrder(如[MATHS, ENGLISH, SCIENCE, COMPUTER])对学生进行排名 - 排序规则:按科目优先级依次比较分数,优先级高的科目分数高的学生排前;若前一科目分数相同,则比较下一优先级科目;若学生无对应科目分数,视为0分处理
- 完成排序后为学生设置排名(同分学生共享同一排名)
现有类结构
Student.java
private Long id; private String firstName; private String lastName; private List<Subject> subjects; // 需添加rank字段及getter/setter // private Integer rank;
Subject.java
private String name; private Integer marks; // 省略getter/setter
输入示例
[ {"id": 1,"firstName": "Alice", "lastName": "Alice", "subjects": [ {"name": "SCIENCE", "marks": 50}, {"name": "MATHS", "marks": 45}]}, {"id": 2,"firstName": "Bob", "lastName": "Bob", "subjects": [ {"name": "MATHS", "marks": 80}, {"name": "ENGLISH", "marks": 85} ]}, {"id": 3, "firstName": "John","lastName": "John", "subjects": [ {"name": "MATHS", "marks": 80}, {"name": "SCIENCE", "marks": 45}, {"name": "ENGLISH", "marks": 75} ]}, {"id": 4,"firstName": "Thomas","lastName": "Thomas", "subjects": [ {"name": "MATHS", "marks": 90} ]} ]
现有代码问题
原代码仅按科目是否存在筛选排序,未实现同科目分数高低比较,也未处理多科目优先级递进比较逻辑,排名设置逻辑完全缺失。
解决方案
1. 编写科目优先级比较的Comparator
核心实现多科目递进比较的排序逻辑:
private Comparator<Student> getStudentComparator(List<String> subjectPriorityOrder) { return (s1, s2) -> { // 按科目优先级逐科比较分数 for (String subjectName : subjectPriorityOrder) { Integer marks1 = getSubjectMarks(s1, subjectName); Integer marks2 = getSubjectMarks(s2, subjectName); // 分数降序排列,高分在前 int compareResult = marks2.compareTo(marks1); if (compareResult != 0) { return compareResult; } // 分数相同则继续比较下一科目 } // 所有科目分数一致时,按ID升序保证排序稳定性 return s1.getId().compareTo(s2.getId()); }; } // 获取学生指定科目的分数,无对应科目则返回0 private Integer getSubjectMarks(Student student, String subjectName) { return student.getSubjects().stream() .filter(subject -> subject.getName().equals(subjectName)) .findFirst() .map(Subject::getMarks) .orElse(0); }
2. 实现排序与排名逻辑
替换原有sortStudentList方法,完成排序+排名计算:
public List<Student> sortStudentList(List<Student> studentList, List<String> subjectPriorityOrder) { if (studentList == null || studentList.isEmpty() || subjectPriorityOrder == null || subjectPriorityOrder.isEmpty()) { return studentList; } // 复制原列表避免修改输入数据 List<Student> sortedStudents = new ArrayList<>(studentList); // 使用自定义Comparator排序 sortedStudents.sort(getStudentComparator(subjectPriorityOrder)); // 计算排名(处理同分同名次) if (!sortedStudents.isEmpty()) { int currentRank = 1; sortedStudents.get(0).setRank(currentRank); for (int i = 1; i < sortedStudents.size(); i++) { Student current = sortedStudents.get(i); Student previous = sortedStudents.get(i - 1); boolean isSameRank = true; // 校验所有优先级科目分数是否完全一致 for (String subjectName : subjectPriorityOrder) { Integer currentMarks = getSubjectMarks(current, subjectName); Integer prevMarks = getSubjectMarks(previous, subjectName); if (!currentMarks.equals(prevMarks)) { isSameRank = false; break; } } if (isSameRank) { current.setRank(previous.getRank()); } else { currentRank = i + 1; current.setRank(currentRank); } } } return sortedStudents; }
3. 补充Student类的rank字段
给Student类添加排名属性及访问方法:
private Integer rank; public Integer getRank() { return rank; } public void setRank(Integer rank) { this.rank = rank; }
测试结果
针对输入示例,排序后学生顺序及排名为:
- Thomas(MATHS 90)→ 排名1
- Bob(MATHS 80,ENGLISH 85)→ 排名2
- John(MATHS 80,ENGLISH 75)→ 排名3
- Alice(MATHS 45)→ 排名4
内容的提问来源于stack exchange,提问作者Rudra
相关产品推荐
相关产品推荐

