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

如何使用Java Stream的reduce方法累加Stopwatch列表的总Duration时长

用Stream的reduce方法统计报表总耗时

我明白你想把原来的循环累加逻辑改成Stream的reduce实现,刚好你的场景很适合用Stream API来简化代码。先回顾下你的基础代码:

你的Stopwatch类定义:

public class Stopwatch { 
    public String report; 
    public Instant startTime; 
    public Instant endTime; 
    public Duration duration; 
}

原来的循环累加逻辑:

Duration total = Duration.ZERO;
for (Stopwatch s: _reportStats) { 
    total = total.plus(s.duration); 
}

推荐的Stream reduce写法

最贴合你原有逻辑的写法是带初始值的reduce重载,因为你本来就用Duration.ZERO作为初始累加值,这种写法直接对应你的循环逻辑:

Duration total = _reportStats.stream()
    .map(Stopwatch::getDuration) // 先将每个Stopwatch映射为它的duration属性
    .reduce(Duration.ZERO, Duration::plus);

如果你不想单独用map步骤,也可以把逻辑合并到reduce里:

Duration total = _reportStats.stream()
    .reduce(Duration.ZERO, 
            (accumulator, stopwatch) -> accumulator.plus(stopwatch.duration),
            Duration::plus);

代码解释

  • 第一个参数Duration.ZERO:就是你原来代码里的初始累加值,确保即使列表为空,也能返回合法的Duration对象(不会出现null)
  • 第二个参数(累加器):定义了如何把当前的累加结果和单个Stopwatch的duration相加,和你循环里的total = total.plus(s.duration)完全一致
  • 第三个参数(组合器):用于并行流场景下合并不同线程的累加结果,这里直接用Duration::plus就可以,因为Duration的加法是线程安全的;如果是串行流,这个参数不会被实际调用,但语法上必须提供

可选的另一种写法(处理空列表)

如果你想显式处理列表为空的情况,也可以用不带初始值的reduce,它会返回Optional<Duration>,这时你需要用orElse指定默认值:

Optional<Duration> totalOptional = _reportStats.stream()
    .map(Stopwatch::getDuration)
    .reduce(Duration::plus);
Duration total = totalOptional.orElse(Duration.ZERO);

不过这种写法需要额外处理Optional,不如第一种写法简洁,毕竟你的原有逻辑就是默认初始为ZERO,不管列表有没有元素都返回一个Duration对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:36:23