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

Java对象属性按时间累加求和逻辑问题排查

问题描述

我有一个Stats对象的列表:

List<Stats> myStats = [
    {id:3, numberOfTags:60, latestDateTime:2022-12-08T15:00:00},
    {id:1, numberOfTags:50, latestDateTime:2022-12-08T14:00:00},
    {id:1, numberOfTags:10, latestDateTime:2022-12-08T10:00:00},
    {id:1, numberOfTags:15, latestDateTime:2022-12-08T16:00:00},
    {id:2, numberOfTags:20, latestDateTime:2022-12-08T11:00:00},
    {id:3, numberOfTags:30, latestDateTime:2022-12-08T12:00:00},
    {id:2, numberOfTags:200,latestDateTime:2022-12-09T13:00:00},
    {id:2, numberOfTags:40, latestDateTime:2022-12-08T13:00:00}
]

需求是对每个latestDateTime对应的numberOfTags求和,规则为:若某个时间点仅单个id有numberOfTags值,其他id需使用该id最近一次的numberOfTags值补充后再求和。例如2022-12-08T11:00:00时,仅id:2有20个numberOfTags,需补充id:1上一个时间点的10个,总和为30。

预期的目标结果:

{
    2022-12-08T10:00:00 = 10,
    2022-12-08T11:00:00 = 30,
    2022-12-08T12:00:00 = 60,
    2022-12-08T13:00:00 = 80,
    2022-12-08T14:00:00 = 120,
    2022-12-08T15:00:00 = 150,
    2022-12-08T16:00:00 = 115,
    2022-12-09T13:00:00 = 275
}

我编写了对应的Java代码,但输出结果不符合预期,请问代码哪里出错了?

附上我的Java代码:

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.Comparator;

public class Main {
    public static void main(String[] args) {
        List<Stats> myStats = List.of(
                new Stats(1, 10, LocalDateTime.parse("2022-12-08T10:00:00")),
                new Stats(2, 20, LocalDateTime.parse("2022-12-08T11:00:00")),
                new Stats(3, 30, LocalDateTime.parse("2022-12-08T12:00:00")),
                new Stats(2, 40, LocalDateTime.parse("2022-12-08T13:00:00")),
                new Stats(1, 50, LocalDateTime.parse("2022-12-08T14:00:00")),
                new Stats(3, 60, LocalDateTime.parse("2022-12-08T15:00:00")),
                new Stats(1, 15, LocalDateTime.parse("2022-12-08T16:00:00")),
                new Stats(2, 200, LocalDateTime.parse("2022-12-09T13:00:00")) 
        );

        List<Stats> sortedStats = myStats.stream()
            .sorted(Comparator.comparing(Stats::getLatestDateTime))
            .collect(Collectors.toList());
    
        Map<LocalDateTime, Integer> tagCountByDateTime = new HashMap<>();
        int previousTagCount = 0;

        for (Stats stats : sortedStats) {
            LocalDateTime dateTime =stats.getLatestDateTime();
            int tagCount = stats.getNumberOfTags();

            if (tagCountByDateTime.containsKey(dateTime)) {
                tagCountByDateTime.put(dateTime, tagCountByDateTime.get(dateTime) + tagCount);
            } else {
                tagCountByDateTime.put(dateTime, previousTagCount + tagCount);
            }

            previousTagCount += tagCount;
        }

        // Then you can iterate over the map to get the sum of tag counts by date time
        for (Map.Entry<LocalDateTime, Integer> entry : tagCountByDateTime.entrySet()) {
            LocalDateTime dateTime = entry.getKey();
            int tagCount = entry.getValue();

            System.out.println(dateTime + ": " + tagCount);
        }
    }
}
    
class Stats {
    private int id;
    private int numberOfTags;
    private LocalDateTime latestDateTime;

    public Stats(int id, int numberOfTags, LocalDateTime latestDateTime) {
        this.id = id;
        this.numberOfTags = numberOfTags;
        this.latestDateTime = latestDateTime;
    }

    public int getId() {
        return id;
    }

    public int getNumberOfTags() {
        return numberOfTags;
    }

    public LocalDateTime getLatestDateTime() {
        return latestDateTime;
    }
}

问题分析与修正

你的代码核心错误在于没有按id跟踪每个id的最新标签数,而是用一个全局的previousTagCount累加所有标签数,这完全不符合需求中“每个id单独取最近值”的规则。

具体问题点:

  • previousTagCount是全局累加变量,会把所有历史标签数无差别加总,而非每个id保留最新值
  • 处理同一时间点的多个id时,仅简单累加当前id的标签数,未补充其他id的最新值
  • 无法维护每个id的状态变化,导致后续时间点的求和逻辑完全偏离需求

修正思路

  1. 用Map<Integer, Integer>跟踪每个id的最新标签数,key为id,value为该id当前的最新标签数
  2. 先收集所有唯一时间点并排序,确保按时间顺序处理
  3. 对每个时间点:
    • 先更新该时间点所有id的最新标签数
    • 再计算所有id的最新标签数之和,作为该时间点的结果

修正后的代码

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<Stats> myStats = List.of(
                new Stats(1, 10, LocalDateTime.parse("2022-12-08T10:00:00")),
                new Stats(2, 20, LocalDateTime.parse("2022-12-08T11:00:00")),
                new Stats(3, 30, LocalDateTime.parse("2022-12-08T12:00:00")),
                new Stats(2, 40, LocalDateTime.parse("2022-12-08T13:00:00")),
                new Stats(1, 50, LocalDateTime.parse("2022-12-08T14:00:00")),
                new Stats(3, 60, LocalDateTime.parse("2022-12-08T15:00:00")),
                new Stats(1, 15, LocalDateTime.parse("2022-12-08T16:00:00")),
                new Stats(2, 200, LocalDateTime.parse("2022-12-09T13:00:00"))
        );

        // 按时间分组,同一时间点的Stats集合在一起
        Map<LocalDateTime, List<Stats>> statsByTime = myStats.stream()
                .collect(Collectors.groupingBy(Stats::getLatestDateTime));

        // 获取所有时间点并按自然顺序排序
        List<LocalDateTime> sortedTimes = new ArrayList<>(statsByTime.keySet());
        sortedTimes.sort(Comparator.naturalOrder());

        // 维护每个id的最新标签数
        Map<Integer, Integer> latestTagPerId = new HashMap<>();
        // 存储最终结果,用LinkedHashMap保证输出顺序与时间顺序一致
        Map<LocalDateTime, Integer> result = new LinkedHashMap<>();

        for (LocalDateTime time : sortedTimes) {
            // 更新当前时间点所有id的最新标签数
            List<Stats> currentStats = statsByTime.get(time);
            for (Stats stat : currentStats) {
                latestTagPerId.put(stat.getId(), stat.getNumberOfTags());
            }

            // 计算所有id的最新标签数之和
            int sum = latestTagPerId.values().stream().mapToInt(Integer::intValue).sum();
            result.put(time, sum);
        }

        // 输出结果
        for (Map.Entry<LocalDateTime, Integer> entry : result.entrySet()) {
            System.out.println(entry.getKey() + " = " + entry.getValue());
        }
    }
}

class Stats {
    private int id;
    private int numberOfTags;
    private LocalDateTime latestDateTime;

    public Stats(int id, int numberOfTags, LocalDateTime latestDateTime) {
        this.id = id;
        this.numberOfTags = numberOfTags;
        this.latestDateTime = latestDateTime;
    }

    public int getId() {
        return id;
    }

    public int getNumberOfTags() {
        return numberOfTags;
    }

    public LocalDateTime getLatestDateTime() {
        return latestDateTime;
    }
}

代码说明

  • statsByTime:将原始数据按时间分组,方便快速获取每个时间点的所有Stats记录
  • sortedTimes:确保按时间顺序处理,保证id的最新值严格遵循时间线更新
  • latestTagPerId:实时维护每个id的最新标签数,每次处理时间点时先更新该时间点的id值,再求和
  • LinkedHashMap:保证结果输出顺序与时间顺序一致,符合直观认知

运行修正后的代码,输出结果将完全符合预期。

内容的提问来源于stack exchange,提问作者Eddie Kwasi Dankie

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 04:35:52