[英]How to sum a triple nested map with Java 8 Collectors
我有這個 map Map<LocalDate, Map<Integer, Map<EHourQuarter, Double>>>
EHourQuarter 是一個枚舉:
public enum EHourQuarter {
FIRST(0, 14, 15),
SECOND(15, 29, 30),
THIRD(30, 44, 45),
FOURTH(45, 59, 60);
private Integer start;
private Integer end;
private Integer value;//this is for UI purposes
}
使用如下值:{2020-07-07 -> {0 -> {EHourQuarter.FIRST -> 5.5, EHourQuarter.SECOND -> 10.2, ...}, 1 -> {EHourQuarter.FIRST -> 33.2, EHourQuarter.SECOND -> 30.1, ...}, ...},
2020-07-08 -> {0 -> {EHourQuarter.FIRST -> 5.5, EHourQuarter.SECOND -> 10.2, ...}, 1 -> {EHourQuarter.FIRST -> 33.2, EHourQuarter.SECOND -> 30.1, . ..}, ... }
It's a map of LocalDate of map of Integer (hour: from 0 to 23) of map of EHourQuarter of Double.
我需要得到一個包含每個日期累積的 Map<Integer(hour), Map<EHourQuarter, Double>>,這意味着如果日期 2020-07-07 到 2020-07-10(4 天)包含在小時 0每個 EHourQuarter 每一個 5,那么結果應該顯示在 0 小時,每個季度的值為 20。
此外,如果通過這樣做,您還可以幫助我將其映射到像這樣的 DTO 列表,
public class QuarterlyOccupancyDTO {
private Integer hour;
private Integer minute;//this is the value property of EHourQuarter
private Double occupancy;
}
我會很感激的。
最后,DTO 列表應包含按小時和分鍾分組的所有日期的總和(EHourQuarter 的 value 屬性)。
這是一個例子。
注意:map 可以包含多個日期,目的是對所有日期進行分組/求和。
鑒於此 map:
{
"2020-06-26":{
"0":{
"FOURTH":0.0,
"FIRST":0.0,
"THIRD":0.0,
"SECOND":0.0
},
"1":{
"FOURTH":0.0,
"FIRST":0.0,
"THIRD":0.0,
"SECOND":0.0
},
"2":{
"FOURTH":0.0,
"FIRST":0.0,
"THIRD":0.0,
"SECOND":0.0
},
"3":{
"FOURTH":0.0,
"FIRST":0.0,
"THIRD":0.0,
"SECOND":0.0
},
"4":{
"FOURTH":0.0,
"FIRST":0.0,
"THIRD":0.0,
"SECOND":0.0
},
"5":{
"FOURTH":0.0,
"FIRST":0.0,
"THIRD":0.0,
"SECOND":0.0
},
"6":{
"FOURTH":0.0,
"FIRST":0.0,
"THIRD":0.0,
"SECOND":0.0
},
"7":{
"FOURTH":0.0,
"FIRST":0.0,
"THIRD":0.0,
"SECOND":0.0
},
"8":{
"FOURTH":0.0,
"FIRST":0.0,
"THIRD":0.0,
"SECOND":0.0
},
"9":{
"FOURTH":5.0,
"FIRST":5.0,
"THIRD":5.0,
"SECOND":5.0
},
"10":{
"FOURTH":5.0,
"FIRST":5.0,
"THIRD":5.0,
"SECOND":5.0
},
"11":{
"FOURTH":5.0,
"FIRST":5.0,
"THIRD":5.0,
"SECOND":5.0
},
"12":{
"FOURTH":5.0,
"FIRST":5.0,
"THIRD":5.0,
"SECOND":5.0
},
"13":{
"FOURTH":5.0,
"FIRST":5.0,
"THIRD":5.0,
"SECOND":5.0
},
"14":{
"FOURTH":5.0,
"FIRST":5.0,
"THIRD":5.0,
"SECOND":5.0
},
"15":{
"FOURTH":5.0,
"FIRST":5.0,
"THIRD":5.0,
"SECOND":5.0
},
"16":{
"FOURTH":5.0,
"FIRST":5.0,
"THIRD":5.0,
"SECOND":5.0
},
"17":{
"FOURTH":5.0,
"FIRST":5.0,
"THIRD":5.0,
"SECOND":5.0
},
"18":{
"FOURTH":0.0,
"FIRST":5.0,
"THIRD":0.0,
"SECOND":0.0
},
"19":{
"FOURTH":0.0,
"FIRST":0.0,
"THIRD":0.0,
"SECOND":0.0
},
"20":{
"FOURTH":0.0,
"FIRST":0.0,
"THIRD":0.0,
"SECOND":0.0
},
"21":{
"FOURTH":0.0,
"FIRST":0.0,
"THIRD":0.0,
"SECOND":0.0
},
"22":{
"FOURTH":0.0,
"FIRST":0.0,
"THIRD":0.0,
"SECOND":0.0
},
"23":{
"FOURTH":0.0,
"FIRST":0.0,
"THIRD":0.0,
"SECOND":0.0
}
}
}
像這樣的列表應該是答案:
[
{
"hour":0,
"minute":15,
"occupancy":0.0
},
{
"hour":0,
"minute":30,
"occupancy":0.0
},
{
"hour":0,
"minute":45,
"occupancy":0.0
},
{
"hour":0,
"minute":60,
"occupancy":0.0
},
{
"hour":1,
"minute":15,
"occupancy":0.0
},
{
"hour":1,
"minute":30,
"occupancy":0.0
},
{
"hour":1,
"minute":45,
"occupancy":0.0
},
{
"hour":1,
"minute":60,
"occupancy":0.0
},
{
"hour":2,
"minute":15,
"occupancy":0.0
},
{
"hour":2,
"minute":30,
"occupancy":0.0
},
{
"hour":2,
"minute":45,
"occupancy":0.0
},
{
"hour":2,
"minute":60,
"occupancy":0.0
},
{
"hour":3,
"minute":15,
"occupancy":0.0
},
{
"hour":3,
"minute":30,
"occupancy":0.0
},
{
"hour":3,
"minute":45,
"occupancy":0.0
},
{
"hour":3,
"minute":60,
"occupancy":0.0
},
{
"hour":4,
"minute":15,
"occupancy":0.0
},
{
"hour":4,
"minute":30,
"occupancy":0.0
},
{
"hour":4,
"minute":45,
"occupancy":0.0
},
{
"hour":4,
"minute":60,
"occupancy":0.0
},
{
"hour":5,
"minute":15,
"occupancy":0.0
},
{
"hour":5,
"minute":30,
"occupancy":0.0
},
{
"hour":5,
"minute":45,
"occupancy":0.0
},
{
"hour":5,
"minute":60,
"occupancy":0.0
},
{
"hour":6,
"minute":15,
"occupancy":0.0
},
{
"hour":6,
"minute":30,
"occupancy":0.0
},
{
"hour":6,
"minute":45,
"occupancy":0.0
},
{
"hour":6,
"minute":60,
"occupancy":0.0
},
{
"hour":7,
"minute":15,
"occupancy":0.0
},
{
"hour":7,
"minute":30,
"occupancy":0.0
},
{
"hour":7,
"minute":45,
"occupancy":0.0
},
{
"hour":7,
"minute":60,
"occupancy":0.0
},
{
"hour":8,
"minute":15,
"occupancy":0.0
},
{
"hour":8,
"minute":30,
"occupancy":0.0
},
{
"hour":8,
"minute":45,
"occupancy":0.0
},
{
"hour":8,
"minute":60,
"occupancy":0.0
},
{
"hour":9,
"minute":15,
"occupancy":5.0
},
{
"hour":9,
"minute":30,
"occupancy":5.0
},
{
"hour":9,
"minute":45,
"occupancy":5.0
},
{
"hour":9,
"minute":60,
"occupancy":5.0
},
{
"hour":10,
"minute":15,
"occupancy":5.0
},
{
"hour":10,
"minute":30,
"occupancy":5.0
},
{
"hour":10,
"minute":45,
"occupancy":5.0
},
{
"hour":10,
"minute":60,
"occupancy":5.0
},
{
"hour":11,
"minute":15,
"occupancy":5.0
},
{
"hour":11,
"minute":30,
"occupancy":5.0
},
{
"hour":11,
"minute":45,
"occupancy":5.0
},
{
"hour":11,
"minute":60,
"occupancy":5.0
},
{
"hour":12,
"minute":15,
"occupancy":5.0
},
{
"hour":12,
"minute":30,
"occupancy":5.0
},
{
"hour":12,
"minute":45,
"occupancy":5.0
},
{
"hour":12,
"minute":60,
"occupancy":5.0
},
{
"hour":13,
"minute":15,
"occupancy":5.0
},
{
"hour":13,
"minute":30,
"occupancy":5.0
},
{
"hour":13,
"minute":45,
"occupancy":5.0
},
{
"hour":13,
"minute":60,
"occupancy":5.0
},
{
"hour":14,
"minute":15,
"occupancy":5.0
},
{
"hour":14,
"minute":30,
"occupancy":5.0
},
{
"hour":14,
"minute":45,
"occupancy":5.0
},
{
"hour":14,
"minute":60,
"occupancy":5.0
},
{
"hour":15,
"minute":15,
"occupancy":5.0
},
{
"hour":15,
"minute":30,
"occupancy":5.0
},
{
"hour":15,
"minute":45,
"occupancy":5.0
},
{
"hour":15,
"minute":60,
"occupancy":5.0
},
{
"hour":16,
"minute":15,
"occupancy":5.0
},
{
"hour":16,
"minute":30,
"occupancy":5.0
},
{
"hour":16,
"minute":45,
"occupancy":5.0
},
{
"hour":16,
"minute":60,
"occupancy":5.0
},
{
"hour":17,
"minute":15,
"occupancy":5.0
},
{
"hour":17,
"minute":30,
"occupancy":5.0
},
{
"hour":17,
"minute":45,
"occupancy":5.0
},
{
"hour":17,
"minute":60,
"occupancy":5.0
},
{
"hour":18,
"minute":15,
"occupancy":5.0
},
{
"hour":18,
"minute":30,
"occupancy":0.0
},
{
"hour":18,
"minute":45,
"occupancy":0.0
},
{
"hour":18,
"minute":60,
"occupancy":0.0
},
{
"hour":19,
"minute":15,
"occupancy":0.0
},
{
"hour":19,
"minute":30,
"occupancy":0.0
},
{
"hour":19,
"minute":45,
"occupancy":0.0
},
{
"hour":19,
"minute":60,
"occupancy":0.0
},
{
"hour":20,
"minute":15,
"occupancy":0.0
},
{
"hour":20,
"minute":30,
"occupancy":0.0
},
{
"hour":20,
"minute":45,
"occupancy":0.0
},
{
"hour":20,
"minute":60,
"occupancy":0.0
},
{
"hour":21,
"minute":15,
"occupancy":0.0
},
{
"hour":21,
"minute":30,
"occupancy":0.0
},
{
"hour":21,
"minute":45,
"occupancy":0.0
},
{
"hour":21,
"minute":60,
"occupancy":0.0
},
{
"hour":22,
"minute":15,
"occupancy":0.0
},
{
"hour":22,
"minute":30,
"occupancy":0.0
},
{
"hour":22,
"minute":45,
"occupancy":0.0
},
{
"hour":22,
"minute":60,
"occupancy":0.0
},
{
"hour":23,
"minute":15,
"occupancy":0.0
},
{
"hour":23,
"minute":30,
"occupancy":0.0
},
{
"hour":23,
"minute":45,
"occupancy":0.0
},
{
"hour":23,
"minute":60,
"occupancy":0.0
}
]
首先使用flatMap
創建Stream<SimpleEntry<Integer, EHourQuarter>, Double>
然后使用toMap
collect as Map<SimpleEntry<Integer, EHourQuarter>, Double>
。 然后 map 進入你的 DTO class。
List<QuarterlyOccupancyDTO> result = map.entrySet().stream()
.flatMap(d -> d.getValue().entrySet().stream()
.flatMap(h -> h.getValue().entrySet().stream().map(
e -> new SimpleEntry<>(new SimpleEntry<>(h.getKey(), e.getKey()), e.getValue()))))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a + b))
.entrySet()
.stream()
.map(m -> new QuarterlyOccupancyDTO(m.getKey().getKey(), m.getKey().getValue().getValue(), m.getValue()))
.collect(Collectors.toList());
注意:由於您沒有顯示代碼,因此某些部分可能無法正常工作。 完整代碼在這里
第一組並按小時/季度對合計占用率
(避免嵌套flatMap
,因為它降低了代碼的可讀性)
Map<Entry<Integer, Integer>, Double> groups
= map.entrySet()
.stream()
// Flatten the outer map, since you don't care about the days
.flatMap(de -> de.getValue().entrySet().stream())
// Flatten the map by combining hour key and quarter key into a single one
.flatMap(he -> he.getValue()
.entrySet()
.stream()
.map(qe -> new SimpleEntry<>(new SimpleEntry<>(he.getKey(), qe.getKey().getValue()), qe.getValue())))
// Sum the occupancy per each hour/quarter pair
.collect(groupingBy(Entry::getKey, summingDouble(Entry::getValue)));
然后 map 將分組條目放入您的 DTO 對象
List<QuarterlyOccupancyDTO> list =
groups.entrySet()
.stream()
.map(e -> new QuarterlyOccupancyDTO(e.getKey().getKey(), e.getKey().getValue(), e.getValue()))
.collect(toList());
另一種純函數方法:
(它是純粹的,但似乎不太可讀,IMO)
Collection<QuarterlyOccupancyDTO> dtos =
map.entrySet()
.stream()
// Flatten the outer map, since you don't care about the days
.flatMap(de -> de.getValue().entrySet()
.stream())
// Flatten the map by merging hour key and quarter key into a single one
.flatMap(he -> he.getValue()
.entrySet()
.stream()
.map(qe -> new SimpleEntry<>(new SimpleEntry<>(he.getKey(), qe.getKey().getValue()),
qe.getValue())))
// Map each entry into a DTO object and then reduce the occupancy per each hour/quarter pair
.collect(
groupingBy(Entry::getKey,
mapping(e -> new QuarterlyOccupancyDTO(e.getKey().getKey(), e.getKey().getValue(), e.getValue()),
reducing(new QuarterlyOccupancyDTO(0, 0, 0.0),
(a, b) -> new QuarterlyOccupancyDTO(b.getHour(), b.getMinute(), a.getOccupancy() + b.getOccupancy())))))
.values();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.