I am provided with a List<Result>
The Result class has a number of fields of which five are of interest
class Result {
public enum SESSION_TYPE {
NIGHT,
DAY
}
private SESSION_TYPE sessionType;
private String sessionDateTime;
private String sessionDate;
private Double consumed;
private Double cost;
...
getters and setters
}
I have created a map as follows
Map<String,List<Result>> dailyResults = results.stream().collect(Collectors.groupingBy(Result::getSessionDate));
I would now like to create a new map keyed on the same sessionDate which contains the summed consumed and cost fields grouped by the SESSION_TYPE, thus
Map<String, Map<String,SessionDetail>> sessionResults
i.e., Map<SessionDate, Map<SessionType,SessionDeatail>>
where the SessionDetail is a record as follows -
record SessionDetail(Result.SESSION_TYPE sessionType, Double consumedTotal, Double costTotal) {};
I've spent some time on this without achieving the desired result. Any help would be much appreciated.
CodePudding user response:
You can do as follows:
Here is some data.
List<Result> results = new ArrayList<>(List.of(
new Result(Result.SESSION_TYPE.DAY, "T1", "27-Dec-2022", 10., 1.),
new Result(Result.SESSION_TYPE.DAY, "T1", "27-Dec-2022", 10., 2.),
new Result(Result.SESSION_TYPE.DAY, "T1", "27-Dec-2022", 10., 3.),
new Result(Result.SESSION_TYPE.NIGHT, "T1", "26-Dec-2022", 10., 20.),
new Result(Result.SESSION_TYPE.NIGHT, "T1", "26-Dec-2022", 10., 30.),
new Result(Result.SESSION_TYPE.DAY, "T1", "26-Dec-2022", 10., 40.),
new Result(Result.SESSION_TYPE.DAY, "T1", "27-Dec-2022", 10., 10.),
new Result(Result.SESSION_TYPE.DAY, "T1", "27-Dec-2022", 10., 10.)));
The original results can be first categorized by the Date
. Then using toMap
,
take the session type
as the key and then create a new instance, summing the values in the previous instance to the one just encountered.
Map<String, Map<Result.SESSION_TYPE, SessionDetail>> dailyResults = results
.stream()
.collect(Collectors.groupingBy(Result::getSessionDate,
Collectors.toMap(Result::getSessionType,
r -> new SessionDetail(r.getSessionType(),
r.getConsumed(), r.getCost()),
(a, b) -> new SessionDetail(b.sessionType,
a.consumedTotal b.consumedTotal,
a.costTotal b.costTotal))));
Print the results as follows:
dailyResults.entrySet().forEach(e -> {
System.out.println(e.getKey());
e.getValue().entrySet()
.forEach(s -> System.out.println(" " s));
});
prints
27-Dec-2022
DAY=SessionDetail[sessionType=DAY, consumedTotal=50.0, costTotal=26.0]
26-Dec-2022
NIGHT=SessionDetail[sessionType=NIGHT, consumedTotal=20.0, costTotal=50.0]
DAY=SessionDetail[sessionType=DAY, consumedTotal=10.0, costTotal=40.0]
The above works without making any changes to your classes. Since record values are final a new record much be created to replace the previous one using the accumulated sums.