I have this java List of objects
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.
When only 1 id has value for numberOfTags
for a specific latestDateTime
we add the previous value of numberOfTags
from previous latestDateTime
.
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
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
{
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. Works since Java 14.