Java中对Map<String, List<Obj>>内BigDecimal求和的优雅实现方案求助
优雅实现Map<String, List>中所有Obj的BigDecimal属性求和(Java Streams版)
嘿,这个需求用Java Streams确实能写出非常简洁优雅的代码,我来给你分享几种靠谱的实现方式,都是我日常开发里常用的:
基础实现(假设getB不会返回null)
如果你的Obj.getB()方法保证不会返回null,那这段代码就足够简洁:
BigDecimal total = myMap.values() .stream() // 将所有嵌套的List<Obj>扁平化为单个Obj的流,避免嵌套循环 .flatMap(List::stream) // 提取每个Obj的BigDecimal属性b .map(Obj::getB) // 从BigDecimal.ZERO开始,依次累加所有值 .reduce(BigDecimal.ZERO, BigDecimal::add);
代码解释:
myMap.values():先拿到Map中所有的List<Obj>集合flatMap(List::stream):把多个List拆成连续的Obj流,这是处理嵌套集合的关键一步map(Obj::getB):将每个对象转换为我们需要求和的BigDecimal属性reduce(BigDecimal.ZERO, BigDecimal::add):BigDecimal没有Stream默认的sum()方法,所以用reduce来实现累加,初始值必须设为BigDecimal.ZERO,否则空流会返回null
安全实现(处理getB可能返回null的情况)
如果getB()有可能返回null,一定要加上过滤逻辑,避免抛出NullPointerException:
import java.util.Objects; BigDecimal total = myMap.values() .stream() .flatMap(List::stream) .map(Obj::getB) // 过滤掉所有null值,确保后续add操作安全 .filter(Objects::nonNull) .reduce(BigDecimal.ZERO, BigDecimal::add);
另一种风格:用Collectors.reducing收集器
如果你更喜欢用收集器的写法,也可以这样实现,效果完全相同:
import java.util.stream.Collectors; BigDecimal total = myMap.values() .stream() .flatMap(List::stream) .collect(Collectors.reducing( BigDecimal.ZERO, // 初始值 Obj::getB, // 提取属性的函数 BigDecimal::add // 累加逻辑 ));
这几种写法都完全摒弃了传统的嵌套循环,用流式API实现了声明式的求和逻辑,代码简洁易读,非常符合Java 8+的优雅编码风格。
内容的提问来源于stack exchange,提问作者user2220232
相关产品推荐
相关产品推荐

