You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将含内部迭代器的增强for循环转换为Stream并实现值求和?

用Stream实现按月累加里程费用的正确姿势

嘿,你的思路已经走对大半啦!问题就卡在Collectors.toMap的第三个合并函数上——你现在写的(k1, k2) -> k1只是保留了第一个遇到的值,但我们需要的是把相同月份的数值累加起来。

完整的Stream解决方案

Map<Month, Integer> data = scooters.stream()
    .flatMap(scooter -> scooter.getRentalDays().stream()
        .map(date -> Map.entry(date.getMonth(), scooter.getMileage() * scooter.getMileageRate())))
    .collect(Collectors.toMap(
        Map.Entry::getKey,
        Map.Entry::getValue,
        // 把重复key的新旧值相加,替换原来的保留第一个值的逻辑
        (existingVal, newVal) -> existingVal + newVal
    ));

来拆解一下这段代码的逻辑:

  • 第一步scooters.stream():把你的scooter集合转换成Stream,开启链式操作。
  • 第二步flatMap(...):每个scooter对应多个租赁日期,用flatMap把每个日期转成一个(月份, 该scooter的里程费用)的Entry,这样所有scooter的所有日期Entry会被平铺成一个统一的流。
  • 第三步collect(Collectors.toMap(...)):
    • 第一个参数Map.Entry::getKey:指定用Entry里的月份作为最终Map的key。
    • 第二个参数Map.Entry::getValue:指定用Entry里的里程费用作为初始value。
    • 第三个参数就是你之前没写对的地方——当遇到同一个月份的key时,把已有的值和新进来的值相加,这样就实现了按月累加的效果。

还有一种更直观的写法(可选)

如果你觉得用Map.entry有点绕,也可以用groupingBy配合summingInt,语义上更贴近“按月份分组求和”的需求,可读性可能更好:

Map<Month, Integer> data = scooters.stream()
    .flatMap(scooter -> scooter.getRentalDays().stream()
        .map(date -> new AbstractMap.SimpleEntry<>(date.getMonth(), scooter.getMileage() * scooter.getMileageRate())))
    .collect(Collectors.groupingBy(
        Map.Entry::getKey,
        Collectors.summingInt(Map.Entry::getValue)
    ));

这里先按月份分组,再对每组里的所有里程费用求和,逻辑一目了然。

内容的提问来源于stack exchange,提问作者Richard Avalos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:30:14