简体   繁体   English

java object 属性累计求和

[英]Accumulated summing of java object properties

I have this java List of objects我有这个 java 对象列表

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}
]

I need to sum all numberOfTags on each LocalDateTime of the latestDateTime property.我需要对latestDateTime属性的每个LocalDateTime上的所有numberOfTags求和。

When only 1 id has value for numberOfTags for a specific latestDateTime we add the previous value of numberOfTags from previous latestDateTime .当只有 1 个 id 具有特定latestDateTimenumberOfTags值时,我们添加之前latestDateTimenumberOfTags的先前值。

For example on 2022-12-08T11:00:00 Total numerOfTags should be 30 because id :2 has numberOfTags : 20 and its only value for that LocalDateTime so we repeat the numberOfTags for 2022-12-08T10:00:00 which was 10 for id :1 making total numberOfTags for 2022-12-08T11:00:00 30 because 10 + 20. So the rule is sum each row where 0 replace with previous value Image below explains it better例如在 2022-12-08T11:00:00 Total numerOfTags应该是 30 因为id :2 有numberOfTags : 20 并且它是那个LocalDateTime的唯一值所以我们重复numberOfTags为 2022-12-08T10:00:00 这是 10对于id :1 使 2022-12-08T11:00:00 的总numberOfTags为 30,因为 10 + 20。所以规则是对每一行求和,其中 0 替换为以前的值 下面的图片解释得更好

在此处输入图像描述

Here is my code这是我的代码

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;
    }
}

result for numOfTagsByDateTime should be numOfTagsByDateTime 的结果应该是

{
    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
}

What am I doing wrong?我究竟做错了什么?

With the clarified requirements I found a solution that brings the expected result:有了明确的要求,我找到了一个带来预期结果的解决方案:

package examples.stackoverflow.q75042726;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Q75042726 {

  private record Stats(Integer id, Integer numberOfTags, LocalDateTime latestDateTime) {
  }

  public static void main(String[] args) {
    List<Stats> statistics = List.of(new Stats(3, 60, LocalDateTime.of(2022, 12, 8, 15, 0, 0)), new Stats(1, 50, LocalDateTime.of(2022, 12, 8, 14, 0, 0)), new Stats(1, 10, LocalDateTime.of(2022, 12, 8, 10, 0, 0)), new Stats(1, 15, LocalDateTime.of(2022, 12, 8, 16, 0, 0)), new Stats(2, 20, LocalDateTime.of(2022, 12, 8, 11, 0, 0)), new Stats(3, 30, LocalDateTime.of(2022, 12, 8, 12, 0, 0)), new Stats(2, 200, LocalDateTime.of(2022, 12, 9, 13, 0, 0)), new Stats(2, 40, LocalDateTime.of(2022, 12, 8, 13, 0, 0)));
    System.out.println(summarize(statistics));
  }

  private static Map<LocalDateTime, Integer> summarize(List<Stats> items) {
    if (items.size() == 0) {
      return Collections.emptyMap();
    }
    List<Stats> workList = new ArrayList<>(items);
    workList.sort(Comparator.comparing(Stats::latestDateTime));

    int maxId = workList.stream().mapToInt(Stats::id).max().orElse(0);
    int[] values = new int[maxId];
    Arrays.fill(values, 0);

    Map<LocalDateTime, Integer> result = new HashMap<>();

    LocalDateTime previous = workList.get(0).latestDateTime;
    for (Stats current : workList) {
      if (!previous.equals(current.latestDateTime)) {
        result.put(previous, Arrays.stream(values).sum());
      }
      previous = current.latestDateTime;

      int index = current.id - 1;
      values[index] = current.numberOfTags;
    }
    result.put(previous, Arrays.stream(values).sum());
    return result;
  }
}

Please note that I used a Java record instead of your class Stats here for the sake of brevity and also because it's exactly meant for that use.请注意,为了简洁起见,我在这里使用了 Java 记录而不是您的 class Stats ,也因为它正是用于该用途。 Works since Java 14.从 Java 14 开始工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM