Java 8按自定义Student对象多属性分组并生成聚合对象列表
解决方案
原代码错误分析
AbstractMap.SimpleEntry仅支持两个参数的构造方法,无法传入三个字段作为分组键。double是基本数据类型,没有add()方法,求和直接用+运算符即可。
方法一:使用Java 16+ 记录类作为分组键
Java 16引入的记录类会自动生成equals()和hashCode(),非常适合作为多字段分组键:
首先定义记录类:
record StudentKey(String name, int age, String city) {}
然后修改流处理代码:
List<Student> students = // 初始化列表 List<Student> res = new ArrayList<>(students.stream() .collect(Collectors.toMap( // 用记录类封装三个分组字段 student -> new StudentKey(student.getName(), student.getAge(), student.getCity()), // 初始值为当前Student实例 Function.identity(), // 合并逻辑:对salary和incentive求和,生成新Student (s1, s2) -> new Student( s1.getName(), s1.getAge(), s1.getCity(), s1.getSalary() + s2.getSalary(), s1.getIncentive() + s2.getIncentive() ) )) .values());
方法二:自定义分组键类(兼容Java 8+)
如果使用Java 8,需要自定义包含三个字段的类,并重写equals()和hashCode()以保证分组逻辑正确:
import java.util.Objects; class StudentKey { private String name; private int age; private String city; public StudentKey(String name, int age, String city) { this.name = name; this.age = age; this.city = city; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; StudentKey that = (StudentKey) o; return age == that.age && Objects.equals(name, that.name) && Objects.equals(city, that.city); } @Override public int hashCode() { return Objects.hash(name, age, city); } }
流处理代码与方法一完全一致。
方法三:分组+聚合的清晰写法
用groupingBy先分组,再通过reducing完成聚合,逻辑更直观:
List<Student> res = students.stream() .collect(Collectors.groupingBy( s -> new StudentKey(s.getName(), s.getAge(), s.getCity()), Collectors.collectingAndThen( Collectors.reducing( (s1, s2) -> new Student( s1.getName(), s1.getAge(), s1.getCity(), s1.getSalary() + s2.getSalary(), s1.getIncentive() + s2.getIncentive() ) ), Optional::get ) )) .values() .stream() .collect(Collectors.toList());
reducing负责合并组内的Student实例,collectingAndThen处理聚合后的Optional结果(每组至少有一个元素,get()操作安全)。
验证结果
运行上述代码后,输入的6个Student会被正确分组求和,输出与示例完全一致:
Student("Raj",10,"Pune",30000,300) Student("Raj",20,"Pune",10000,100) Student("Ram",30,"Pune",40000,400) Student("Seema",10,"Pune",10000,100)
内容的提问来源于stack exchange,提问作者prachi Kadam
相关产品推荐
相关产品推荐

