如何按属性分组并获取最大值映射?Java Stream优化实现
按学生分组获取最高成绩的Stream优化实现
场景说明
现有StudentGrade类定义如下:
public class StudentGrade { int studentId; double value; Date date; // 省略getter、setter等方法 }
需求是将List<StudentGrade>按studentId分组,得到以studentId为键、对应学生最高成绩的StudentGrade对象为值的Map<Integer, StudentGrade>。原实现需要额外初始化HashMap并处理Optional,以下是无需额外容器、全程用Stream完成的优化方案。
优化方案1:用collectingAndThen包装maxBy
通过collectingAndThen直接将maxBy返回的Optional<StudentGrade>提取为实际值,一步生成目标Map:
public Map<Integer, StudentGrade> getMaxGradeByStudent(List<StudentGrade> grades) { return grades.stream().collect( Collectors.groupingBy( StudentGrade::getStudentId, Collectors.collectingAndThen( Collectors.maxBy(Comparator.comparing(StudentGrade::getValue)), Optional::get ) ) ); }
注意:若某
studentId对应分组为空(原列表无该学生数据),Optional::get会抛出NoSuchElementException,可根据业务需求改用Optional.orElse(null)或指定默认值。
优化方案2:直接使用Collectors.toMap
利用toMap的合并函数,遇到相同studentId的元素时保留成绩更高的对象,逻辑更简洁且无需处理Optional:
public Map<Integer, StudentGrade> getMaxGradeByStudent(List<StudentGrade> grades) { return grades.stream().collect( Collectors.toMap( StudentGrade::getStudentId, grade -> grade, (existing, newGrade) -> existing.getValue() >= newGrade.getValue() ? existing : newGrade ) ); }
如果存在多个成绩相同的最高记录,此方案会保留先出现的对象;若需按其他维度(如最新date)筛选,可在合并函数中扩展判断逻辑。
内容的提问来源于stack exchange,提问作者ptt
相关产品推荐
相关产品推荐

