List.stream对多个属性值如何一次性进行分别汇总计算

soyestrellafortuna 2021-04-08 11:45:36
我有一个对象集合,其中包含多个需要合计的属性字段。请问各位老师,如何只使用一次就可以分别统计出各维度的合计值?谢谢老师了。

参考的样例

参考的对象,getter,setter略
class Student {
private String id;

private BigDecimal chinese;

private BigDecimal math;

private BigDecimal english;

public Student(String id, BigDecimal chinese, BigDecimal math, BigDecimal english) {
super();
this.id = id;
this.chinese = chinese;
this.math = math;
this.english = english;
}
}


单科计算使用reduce即可统计,但如果统计其他学科,需要多次重复。如何一次返回各科的汇总成绩呢?我想使用数组分别返回,但stream不会处理多个字段的场景。或者各位老师有更好的方案也可以教一下我。谢谢老师了。
	public static void main(String[] args) {
Student zhangsan = new Student("zhangsan", new BigDecimal("87"), new BigDecimal("52"), new BigDecimal("36"));
Student lisi = new Student("lisi", new BigDecimal("91"), new BigDecimal("83.2"), new BigDecimal("78"));
Student wangwu = new Student("wangwu", new BigDecimal("100"), new BigDecimal("64"), new BigDecimal("73"));
Student zhaoliu = new Student("zhaoliu", new BigDecimal("99"), new BigDecimal("92"), new BigDecimal("91"));

List<Student> studentList = new ArrayList<Student>();
studentList.add(zhangsan);
studentList.add(lisi);
studentList.add(wangwu);
studentList.add(zhaoliu);
// 单科成绩 可以进行汇总计算
BigDecimal sum = studentList.stream().map(student -> student.getChinese()).reduce(BigDecimal.ZERO,
BigDecimal::add);
System.out.println("语文总成绩:" + sum.toEngineeringString());

// 多科成绩分别汇总中reduce如何处理?
studentList.stream().map(student -> new BigDecimal[] {student.getChinese(), student.getMath(), student.getEnglish()})
.reduce(new BigDecimal[] {BigDecimal.ZERO,BigDecimal.ZERO,BigDecimal.ZERO}, BigDecimal::add);
}
...全文
5793 5 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复 2
方法一:

    private static BigDecimal calculate(List<Student> studentList, Function<Student,BigDecimal> function){
        return studentList.stream().map(student -> function.apply(student)).reduce(BigDecimal.ZERO,
                BigDecimal::add);
    }
调用方法:
calculate(studentList,Student::getChinese)
方法二:反射


    private static <T> Map<String, BigDecimal> calulateMap(List<T> studentList, Class<T> tClass) throws Exception {
        Field[] declaredFields = tClass.getDeclaredFields();
        Map<Field, BigDecimal> map = new HashMap<>();
        for (Field field : declaredFields) {
            if (field.getType().equals(BigDecimal.class)) {
                field.setAccessible(true);
                map.put(field, BigDecimal.ZERO);
            }
        }

        Set<Map.Entry<Field, BigDecimal>> entries = map.entrySet();
        for (T t : studentList) {
            for (Map.Entry<Field, BigDecimal> entry : entries) {
                entry.setValue(entry.getValue().add((BigDecimal) entry.getKey().get(t)));
            }
        }
        Map<String, BigDecimal> resultMap = new HashMap<>();
        map.entrySet().stream().forEach((k) -> resultMap.put(k.getKey().getName(), k.getValue()));
        return resultMap;
    }
调用方法: calulateMap(studentList,Student.class) 执行结果: {chinese=377, english=278, math=291.2}
soyestrellafortuna 2021-04-08
  • 打赏
  • 举报
回复
引用 3 楼 qq_39936465 的回复:
[quote=引用 2 楼 soyestrellafortuna 的回复:]感谢@长江水面写日记 老师的解答。 我目前处理的一个对象有40+多个字段,其中可能涉及到汇总计算的有十几个字段。类似的对象有七八个。之所以想寻找这么一种方式,只是想尝试将功能抽取出来变成一个工具类。避免大量的单条汇总计算出现。当然,如果老师有更好的解决方案,还请不吝赐教。深表感谢。
我觉得你不如把数据都写入数据库,用sql来多列分别求和。[/quote] 嗯,我考虑一下存储数据库的方案。再次感谢老师。
qq_39936465 2021-04-08
  • 打赏
  • 举报
回复
引用 2 楼 soyestrellafortuna 的回复:
感谢@长江水面写日记 老师的解答。 我目前处理的一个对象有40+多个字段,其中可能涉及到汇总计算的有十几个字段。类似的对象有七八个。之所以想寻找这么一种方式,只是想尝试将功能抽取出来变成一个工具类。避免大量的单条汇总计算出现。当然,如果老师有更好的解决方案,还请不吝赐教。深表感谢。
我觉得你不如把数据都写入数据库,用sql来多列分别求和。
soyestrellafortuna 2021-04-08
  • 打赏
  • 举报
回复
感谢@长江水面写日记 老师的解答。 我目前处理的一个对象有40+多个字段,其中可能涉及到汇总计算的有十几个字段。类似的对象有七八个。之所以想寻找这么一种方式,只是想尝试将功能抽取出来变成一个工具类。避免大量的单条汇总计算出现。当然,如果老师有更好的解决方案,还请不吝赐教。深表感谢。
  • 打赏
  • 举报
回复
BigDecimal[] reduce = studentList.stream().map(student -> new BigDecimal[]{student.getChinese(), student.getMath(), student.getEnglish()})
				.reduce(new BigDecimal[]{BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO},  (a, b) -> {
					for (int i = 0; i < a.length; i++) {
						b[i] = b[i].add(a[i]);
					}
					return b;
				});
你定义的一个数组来收集结果,本质上还是要遍历,这样做意义大吗?

62,630

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧