Java 8 Stream实现POJO按name分组并求和count的技术问询
嘿,你的思路方向是对的,但其实可以用Stream API里的内置收集器来让代码更简洁高效,不用手动写求和逻辑~
直接一步到位完成分组+求和,然后转成目标列表就行,看这个示例:
List<Foo> groupedFoos = foosToSum.stream() .collect(Collectors.groupingBy( Foo::getName, // 按name属性分组 Collectors.summingInt(Foo::getCount) // 自动对每组的count求和 )) .entrySet() .stream() .map(entry -> { // 这里根据你的Foo构造器实例化,date如果不需要可以设为null,或者按业务需求处理 return new Foo(entry.getKey(), null, entry.getValue()); }) .collect(Collectors.toList());
这个写法的优势很明显:
- 不用自己维护
totalCount变量,内置的summingInt收集器会帮你高效完成聚合操作 - 代码更紧凑,避免了额外的分组后列表遍历,性能更优
如果你的业务需要保留每组里的特定date(比如取分组内第一个元素的date),可以换用collectingAndThen来同时获取分组列表和求和结果:
List<Foo> groupedFoos = foosToSum.stream() .collect(Collectors.groupingBy( Foo::getName, Collectors.collectingAndThen( Collectors.toList(), list -> { int totalCount = list.stream().mapToInt(Foo::getCount).sum(); String targetDate = list.get(0).getDate(); // 取分组内第一个元素的date return new Foo(list.get(0).getName(), targetDate, totalCount); } ) )) .values() .stream() .collect(Collectors.toList());
另外注意,如果你的Foo类没有提供全参构造器,就用setter方法来设置属性就行,比如:
.map(entry -> { Foo foo = new Foo(); foo.setName(entry.getKey()); foo.setDate(null); foo.setCount(entry.getValue()); return foo; })
这样写既简洁又高效,比你原来的分步实现要省心多啦~
内容的提问来源于stack exchange,提问作者user1679671
相关产品推荐
相关产品推荐

