解决方案1
/**
* 计算分数排名
* @param allFullScores
*/
public void calculateScoreRank(List<StudentSubjectFullScoreDto> allFullScores) {
Map<Long, StudentSubjectFullScoreDto> stuMap = allFullScores.stream().collect(Collectors.toMap(StudentSubjectFullScoreDto::getStuId, StudentSubjectFullScoreDto->StudentSubjectFullScoreDto));
//过滤掉不统计的数据,这些数据不参与排名
List<StudentSubjectFullScoreDto> scoreRankList = allFullScores.stream().filter(t -> t.getStatisticsStatus() == CommonConst.TYPE_STATISTICS_ENABLE).collect(Collectors.toList());
//按学生单科成绩总分倒序排列
scoreRankList.sort(Comparator.comparingDouble(StudentSubjectFullScoreDto::getSumScore).reversed());
//按分数分组,统计个数
Map<Double, Long> scoreMap = scoreRankList.stream().collect(Collectors.groupingBy(StudentSubjectFullScoreDto::getSumScore, Collectors.counting()));
//初始值名次
int rank = 1;
double scoreRate = 1.0; //此处不需要删除即可
for (int i = 0; i < scoreRankList.size(); i++) {
//得到相同分数的个数
Long count = scoreMap.get(scoreRankList.get(i).getSumScore());
scoreRate=new BigDecimal(scoreRankList.size() - rank).divide(new BigDecimal(scoreRankList.size()), 2, BigDecimal.ROUND_HALF_UP).doubleValue();
if (count == 1) {
StudentSubjectFullScoreDto copyDto = scoreRankList.get(i);
StudentSubjectFullScoreDto sourceDto = stuMap.get(copyDto.getStuId());
sourceDto.setScoreRank(rank++) ;
sourceDto.setScoreRankRate(scoreRate);
}else {
//总分相同,名次相同
for (int j = 0; j < count; j++) {
StudentSubjectFullScoreDto copyDto = scoreRankList.get(i+j);
StudentSubjectFullScoreDto sourceDto = stuMap.get(copyDto.getStuId());
sourceDto.setScoreRank(rank);
sourceDto.setScoreRankRate(scoreRate);
}
//排名还需要按人数顺序数他是第几个
rank= (int) (rank+count);
//连续n个相同的总分,排名一样
i = (int) (i + count -1);
}
}
}
解决方案2
/**
* 排序:把不同成绩保存map中,最后实体类根据map的key找到排名 存入实体排名里面,前端取值。
* @return
*/
public static Map<Double,Integer> rankScore(List<DeductPersonVO> stus) {
Map<Double,Integer> map = new HashMap<>();
List<Map.Entry<Double, List<DeductPersonVO>>> list = stus.stream().collect(Collectors.groupingBy(DeductPersonVO::getDeductScore)).entrySet()
.stream().sorted((s1, s2) -> -Double.compare(s1.getKey(), s2.getKey())).collect(Collectors.toList());
int index = 1;
for (Map.Entry<Double, List<DeductPersonVO>> entry : list) {
map.put(entry.getKey(),index);
entry.getValue().forEach((s) -> System.out.print(" " + s.getDeductScore()));
System.out.println();
index++;
}
return map;
}
取出值存入实体
Map<Double,Integer> rankMap2 = rankScore(personList);
personList.stream().forEach(bean -> {
bean.setRank(rankMap2.get(bean.getDeductScore()));
});