7 changed files with 582 additions and 406 deletions
@ -0,0 +1,30 @@ |
|||
package com.dongjian.dashboard.back.vo.device; |
|||
|
|||
import io.swagger.v3.oas.annotations.media.Schema; |
|||
import lombok.Data; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.HashMap; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
|
|||
@Data |
|||
public class AccumulateLineData { |
|||
|
|||
@Schema(description = "属性编码, 默认:single,温湿度设备:temperature或者humidity") |
|||
private String attrCode; |
|||
|
|||
@Schema(description = "Y-axis data", example = "[]") |
|||
private Map<String, childLineData> subData = new HashMap<>(); |
|||
|
|||
|
|||
@Data |
|||
public static class childLineData { |
|||
@Schema(description = "X-axis data", example = "[]") |
|||
private List<String> xData = new ArrayList<>(); |
|||
|
|||
@Schema(description = "Y-axis data", example = "[]") |
|||
private List<Object> yData = new ArrayList<>(); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,333 @@ |
|||
package com.dongjian.dashboard.back.service.common; |
|||
|
|||
import com.dongjian.dashboard.back.vo.device.AccumulateLineData; |
|||
import com.dongjian.dashboard.back.vo.device.LineData; |
|||
|
|||
import java.time.LocalDate; |
|||
import java.time.LocalDateTime; |
|||
import java.time.LocalTime; |
|||
import java.time.format.DateTimeFormatter; |
|||
import java.util.*; |
|||
|
|||
/** |
|||
* 完整整合版:LineData 聚合与转换工具类(统一使用 LineDataAligner 对齐) |
|||
*/ |
|||
public class LineDataAggregator { |
|||
|
|||
/* =============================== |
|||
* 时间工具 |
|||
* =============================== */ |
|||
public static final class TimeAxisUtil { |
|||
public static final DateTimeFormatter DATETIME_FMT = |
|||
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); |
|||
|
|||
public static String hourKey(LocalDateTime time) { |
|||
return time.withMinute(0).withSecond(0).withNano(0).format(DATETIME_FMT); |
|||
} |
|||
|
|||
public static String halfHourKey(LocalDateTime time) { |
|||
int minute = time.getMinute() < 30 ? 0 : 30; |
|||
return time.withMinute(minute).withSecond(0).withNano(0).format(DATETIME_FMT); |
|||
} |
|||
|
|||
public static String alignToHalfHour(LocalTime time) { |
|||
int minute = time.getMinute() < 30 ? 0 : 30; |
|||
return LocalTime.of(time.getHour(), minute).format(DateTimeFormatter.ofPattern("HH:mm")); |
|||
} |
|||
|
|||
public static String extractDate(String datetime) { |
|||
return LocalDateTime.parse(datetime, DATETIME_FMT).toLocalDate().toString(); |
|||
} |
|||
|
|||
public static List<String> generate48HalfHourPoints(String date) { |
|||
List<String> list = new ArrayList<>(48); |
|||
LocalDateTime t = LocalDate.parse(date).atStartOfDay(); |
|||
for (int i = 0; i < 48; i++) { |
|||
list.add(t.plusMinutes(i * 30).format(DATETIME_FMT)); |
|||
} |
|||
return list; |
|||
} |
|||
} |
|||
|
|||
/* =============================== |
|||
* Y 对齐工具 |
|||
* =============================== */ |
|||
public static final class LineDataAligner { |
|||
|
|||
/** |
|||
* 对齐 X 轴,补 null |
|||
*/ |
|||
public static Map<String, List<Object>> alignY( |
|||
List<String> xAxis, |
|||
Map<String, Map<String, Object>> seriesValueMap |
|||
) { |
|||
Map<String, List<Object>> result = new LinkedHashMap<>(); |
|||
for (Map.Entry<String, Map<String, Object>> entry : seriesValueMap.entrySet()) { |
|||
List<Object> aligned = new ArrayList<>(xAxis.size()); |
|||
Map<String, Object> valueMap = entry.getValue(); |
|||
for (String x : xAxis) { |
|||
aligned.add(valueMap.get(x)); |
|||
} |
|||
result.put(entry.getKey(), aligned); |
|||
} |
|||
return result; |
|||
} |
|||
} |
|||
|
|||
/* =============================== |
|||
* 聚合策略接口(可扩展) |
|||
* =============================== */ |
|||
@FunctionalInterface |
|||
public interface HalfHourCollector<T> { |
|||
void collect(Map<String, T> bucket, String key, LocalDateTime time, Object value); |
|||
} |
|||
|
|||
/* 平均值聚合实现 */ |
|||
public static class AvgCollector implements HalfHourCollector<List<Double>> { |
|||
@Override |
|||
public void collect(Map<String, List<Double>> bucket, String key, LocalDateTime time, Object value) { |
|||
bucket.computeIfAbsent(key, k -> new ArrayList<>()).add(Double.parseDouble(value.toString())); |
|||
} |
|||
} |
|||
|
|||
/* 取最后一条实现 */ |
|||
public static class LastValueCollector implements HalfHourCollector<TimeValue> { |
|||
@Override |
|||
public void collect(Map<String, TimeValue> bucket, String key, LocalDateTime time, Object value) { |
|||
TimeValue old = bucket.get(key); |
|||
if (old == null || time.isAfter(old.time)) { |
|||
bucket.put(key, new TimeValue(time, value)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/* =============================== |
|||
* 核心数据模型 |
|||
* =============================== */ |
|||
public static class TimeValue { |
|||
LocalDateTime time; |
|||
Object value; |
|||
|
|||
TimeValue(LocalDateTime time, Object value) { |
|||
this.time = time; |
|||
this.value = value; |
|||
} |
|||
} |
|||
|
|||
public static class HalfHourSeries { |
|||
String date; |
|||
List<String> xList; |
|||
List<Object> yList; |
|||
|
|||
HalfHourSeries(String date) { |
|||
this(date, new ArrayList<>(), new ArrayList<>()); |
|||
} |
|||
|
|||
HalfHourSeries(String date, List<String> xList, List<Object> yList) { |
|||
this.date = date; |
|||
this.xList = xList; |
|||
this.yList = yList; |
|||
} |
|||
|
|||
Map<String, Object> toMap() { |
|||
Map<String, Object> map = new HashMap<>(); |
|||
for (int i = 0; i < xList.size(); i++) { |
|||
map.put(xList.get(i), yList.get(i)); |
|||
} |
|||
return map; |
|||
} |
|||
} |
|||
|
|||
/* =============================== |
|||
* 工具方法 |
|||
* =============================== */ |
|||
private static Object safeGet(List<Object> list, int index) { |
|||
return (list != null && index < list.size()) ? list.get(index) : null; |
|||
} |
|||
|
|||
private static LocalDateTime parseTime(Object x) { |
|||
return LocalDateTime.parse(String.valueOf(x), TimeAxisUtil.DATETIME_FMT); |
|||
} |
|||
|
|||
/* =============================== |
|||
* 按小时聚合(平均值) |
|||
* =============================== */ |
|||
public static void aggregateByHour(LineData lineData) { |
|||
aggregateByHourOrHalfHour(lineData, new AvgCollector(), true); |
|||
} |
|||
|
|||
/* =============================== |
|||
* 按半小时聚合(平均值) |
|||
* =============================== */ |
|||
public static void aggregateAverageByHalfHour(LineData lineData) { |
|||
aggregateByHourOrHalfHour(lineData, new AvgCollector(), false); |
|||
} |
|||
|
|||
/* 公共聚合方法 */ |
|||
private static <T> void aggregateByHourOrHalfHour( |
|||
LineData lineData, |
|||
HalfHourCollector<T> collector, |
|||
boolean byHour |
|||
) { |
|||
if (lineData == null) return; |
|||
|
|||
List<String> xData = lineData.getXData(); |
|||
Map<String, List<Object>> yDataMap = lineData.getYData(); |
|||
if (xData == null || xData.isEmpty() || yDataMap == null || yDataMap.isEmpty()) return; |
|||
|
|||
Set<String> allSeriesKeys = yDataMap.keySet(); |
|||
|
|||
Map<String, Map<String, T>> bucket = new TreeMap<>(); |
|||
for (int i = 0; i < xData.size(); i++) { |
|||
LocalDateTime time = parseTime(xData.get(i)); |
|||
String key = byHour ? TimeAxisUtil.hourKey(time) : TimeAxisUtil.halfHourKey(time); |
|||
|
|||
for (String series : allSeriesKeys) { |
|||
Object yVal = safeGet(yDataMap.get(series), i); |
|||
if (yVal == null) continue; |
|||
|
|||
bucket.computeIfAbsent(key, k -> new HashMap<>()); |
|||
collector.collect(bucket.get(key), series, time, yVal); |
|||
} |
|||
} |
|||
|
|||
// 构建临时 Map 用于统一对齐
|
|||
Map<String, Map<String, Object>> tmpMap = new HashMap<>(); |
|||
boolean isAvg = collector instanceof AvgCollector; |
|||
|
|||
for (Map.Entry<String, Map<String, T>> entry : bucket.entrySet()) { |
|||
String xKey = entry.getKey(); |
|||
Map<String, T> seriesMap = entry.getValue(); |
|||
for (String series : allSeriesKeys) { |
|||
Object val; |
|||
T tVal = seriesMap.get(series); |
|||
if (isAvg && tVal instanceof List) { |
|||
List<Double> list = (List<Double>) tVal; |
|||
val = list.stream().mapToDouble(Double::doubleValue).average().orElse(0); |
|||
} else if (!isAvg && tVal instanceof TimeValue) { |
|||
val = ((TimeValue) tVal).value; |
|||
} else { |
|||
val = tVal; |
|||
} |
|||
tmpMap.computeIfAbsent(series, k -> new HashMap<>()).put(xKey, val); |
|||
} |
|||
} |
|||
|
|||
List<String> newX = new ArrayList<>(bucket.keySet()); |
|||
lineData.setXData(newX); |
|||
lineData.setYData(LineDataAligner.alignY(newX, tmpMap)); |
|||
} |
|||
|
|||
/* =============================== |
|||
* AccumulateLineData -> LineData |
|||
* 半小时取最后一条 |
|||
* =============================== */ |
|||
public static void convertToLineDataHour(AccumulateLineData accumulate, LineData lineData) { |
|||
if (accumulate == null || accumulate.getSubData() == null) return; |
|||
|
|||
Map<String, HalfHourSeries> seriesMap = new LinkedHashMap<>(); |
|||
for (Map.Entry<String, AccumulateLineData.childLineData> entry : accumulate.getSubData().entrySet()) { |
|||
seriesMap.put(entry.getKey(), aggregateLastByHalfHour(entry.getValue())); |
|||
} |
|||
|
|||
HalfHourSeries today = seriesMap.get("today"); |
|||
if (today == null) throw new IllegalStateException("subData 必须包含 today"); |
|||
|
|||
// 构建最终 X
|
|||
List<String> finalX = new ArrayList<>(); |
|||
for (String hm : today.xList) finalX.add(today.date + " " + hm + ":00"); |
|||
|
|||
// 构建临时 Map
|
|||
Map<String, Map<String, Object>> tmpMap = new HashMap<>(); |
|||
for (Map.Entry<String, HalfHourSeries> entry : seriesMap.entrySet()) { |
|||
tmpMap.put(entry.getKey(), entry.getValue().toMap()); |
|||
} |
|||
|
|||
lineData.setXData(finalX); |
|||
lineData.setYData(LineDataAligner.alignY(today.xList, tmpMap)); |
|||
lineData.setAttrCode(accumulate.getAttrCode()); |
|||
|
|||
fillTo48HalfHour(lineData); |
|||
} |
|||
|
|||
private static HalfHourSeries aggregateLastByHalfHour(AccumulateLineData.childLineData child) { |
|||
if (child == null || child.getXData() == null || child.getYData() == null) |
|||
return new HalfHourSeries(null); |
|||
|
|||
Map<String, TimeValue> bucket = new HashMap<>(); |
|||
String date = null; |
|||
int size = Math.min(child.getXData().size(), child.getYData().size()); |
|||
|
|||
for (int i = 0; i < size; i++) { |
|||
LocalDateTime time = LocalDateTime.parse(child.getXData().get(i).toString(), TimeAxisUtil.DATETIME_FMT); |
|||
Object value = child.getYData().get(i); |
|||
if (value == null) continue; |
|||
|
|||
if (date == null) date = time.toLocalDate().toString(); |
|||
String hm = TimeAxisUtil.alignToHalfHour(time.toLocalTime()); |
|||
|
|||
TimeValue old = bucket.get(hm); |
|||
if (old == null || time.isAfter(old.time)) bucket.put(hm, new TimeValue(time, value)); |
|||
} |
|||
|
|||
List<String> sortedHM = new ArrayList<>(bucket.keySet()); |
|||
Collections.sort(sortedHM); |
|||
|
|||
List<Object> values = new ArrayList<>(); |
|||
for (String hm : sortedHM) values.add(bucket.get(hm).value); |
|||
|
|||
return new HalfHourSeries(date, sortedHM, values); |
|||
} |
|||
|
|||
/* =============================== |
|||
* 补齐 48 半小时点 |
|||
* =============================== */ |
|||
public static void fillTo48HalfHour(LineData lineData) { |
|||
List<String> xData = lineData.getXData(); |
|||
Map<String, List<Object>> yData = lineData.getYData(); |
|||
if (xData == null || xData.isEmpty() || yData == null) return; |
|||
|
|||
String date = TimeAxisUtil.extractDate(xData.get(0)); |
|||
List<String> fixedX = TimeAxisUtil.generate48HalfHourPoints(date); |
|||
|
|||
// 构建临时 Map
|
|||
Map<String, Map<String, Object>> tmpMap = new HashMap<>(); |
|||
for (Map.Entry<String, List<Object>> entry : yData.entrySet()) { |
|||
Map<String, Object> map = new HashMap<>(); |
|||
for (int i = 0; i < xData.size(); i++) { |
|||
map.put(xData.get(i), entry.getValue().get(i)); |
|||
} |
|||
tmpMap.put(entry.getKey(), map); |
|||
} |
|||
|
|||
lineData.setXData(new ArrayList<>(fixedX)); |
|||
lineData.setYData(LineDataAligner.alignY(fixedX, tmpMap)); |
|||
} |
|||
|
|||
/* =============================== |
|||
* 全量对齐 |
|||
* =============================== */ |
|||
public static void convertToLineDataAll(AccumulateLineData accumulate, LineData lineData) { |
|||
if (accumulate == null || accumulate.getSubData() == null) return; |
|||
|
|||
LinkedHashSet<String> xSet = new LinkedHashSet<>(); |
|||
for (AccumulateLineData.childLineData child : accumulate.getSubData().values()) { |
|||
if (child.getXData() != null) xSet.addAll(child.getXData()); |
|||
} |
|||
List<String> mergedX = new ArrayList<>(xSet); |
|||
|
|||
Map<String, Map<String, Object>> tmpMap = new LinkedHashMap<>(); |
|||
for (Map.Entry<String, AccumulateLineData.childLineData> entry : accumulate.getSubData().entrySet()) { |
|||
Map<String, Object> map = new LinkedHashMap<>(); |
|||
AccumulateLineData.childLineData child = entry.getValue(); |
|||
if (child.getXData() != null && child.getYData() != null) { |
|||
int size = Math.min(child.getXData().size(), child.getYData().size()); |
|||
for (int i = 0; i < size; i++) map.put(child.getXData().get(i), child.getYData().get(i)); |
|||
} |
|||
tmpMap.put(entry.getKey(), map); |
|||
} |
|||
|
|||
lineData.setXData(mergedX); |
|||
lineData.setYData(LineDataAligner.alignY(mergedX, tmpMap)); |
|||
} |
|||
} |
|||
@ -1,224 +0,0 @@ |
|||
package com.dongjian.dashboard.back.service.common; |
|||
|
|||
import com.dongjian.dashboard.back.vo.device.LineData; |
|||
|
|||
import java.time.LocalDate; |
|||
import java.time.LocalDateTime; |
|||
import java.time.ZoneId; |
|||
import java.time.format.DateTimeFormatter; |
|||
import java.util.*; |
|||
|
|||
/** |
|||
* 给计测设备,按小时聚合数据,求平均值 |
|||
*/ |
|||
public class LineDataHourAggregator { |
|||
|
|||
private static final DateTimeFormatter INPUT_FMT = |
|||
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); |
|||
|
|||
private static final DateTimeFormatter HOUR_FMT = |
|||
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:00:00"); |
|||
|
|||
public static void aggregateByHour(LineData lineData) { |
|||
|
|||
List<Object> xData = lineData.getXData(); |
|||
Map<String, List<Object>> yDataMap = lineData.getYData(); |
|||
|
|||
if (xData == null || yDataMap == null || yDataMap.isEmpty()) { |
|||
return; |
|||
} |
|||
|
|||
// hour -> index
|
|||
Map<String, Integer> hourIndexMap = new TreeMap<>(); |
|||
Map<String, Map<String, List<Double>>> hourValueMap = new TreeMap<>(); |
|||
|
|||
for (int i = 0; i < xData.size(); i++) { |
|||
String timeStr = String.valueOf(xData.get(i)); |
|||
LocalDateTime time = LocalDateTime.parse(timeStr, INPUT_FMT); |
|||
String hourKey = time.format(HOUR_FMT); |
|||
|
|||
hourIndexMap.putIfAbsent(hourKey, hourIndexMap.size()); |
|||
|
|||
for (Map.Entry<String, List<Object>> entry : yDataMap.entrySet()) { |
|||
Object yVal = entry.getValue().get(i); |
|||
if (yVal == null) { |
|||
continue; |
|||
} |
|||
|
|||
hourValueMap |
|||
.computeIfAbsent(hourKey, k -> new HashMap<>()) |
|||
.computeIfAbsent(entry.getKey(), k -> new ArrayList<>()) |
|||
.add(Double.parseDouble(String.valueOf(yVal))); |
|||
} |
|||
} |
|||
|
|||
List<Object> newX = new ArrayList<>(); |
|||
Map<String, List<Object>> newY = new HashMap<>(); |
|||
|
|||
for (String hourKey : hourIndexMap.keySet()) { |
|||
newX.add(hourKey); |
|||
|
|||
Map<String, List<Double>> seriesMap = hourValueMap.get(hourKey); |
|||
if (seriesMap == null) { |
|||
continue; |
|||
} |
|||
|
|||
for (Map.Entry<String, List<Double>> e : seriesMap.entrySet()) { |
|||
double avg = e.getValue().stream().mapToDouble(Double::doubleValue).average().orElse(0); |
|||
newY.computeIfAbsent(e.getKey(), k -> new ArrayList<>()).add(avg); |
|||
} |
|||
} |
|||
|
|||
lineData.setXData(newX); |
|||
lineData.setYData(newY); |
|||
} |
|||
|
|||
/** |
|||
* 将 LineData 补齐为【日本时区】当天 0:00 - 23:30 的 48 个半小时点 |
|||
* 没有数据的时间点,Y 值补 0 |
|||
*/ |
|||
public static void fillTodayHalfHourPointsJST(LineData lineData) { |
|||
|
|||
List<Object> xData = lineData.getXData(); |
|||
Map<String, List<Object>> yDataMap = lineData.getYData(); |
|||
|
|||
if (xData == null || yDataMap == null) { |
|||
return; |
|||
} |
|||
|
|||
ZoneId JST = ZoneId.of("Asia/Tokyo"); |
|||
LocalDate todayJst = LocalDate.now(JST); |
|||
LocalDateTime start = todayJst.atStartOfDay(); |
|||
|
|||
// 原数据转 Map:time -> series -> value
|
|||
Map<String, Map<String, Object>> valueMap = new HashMap<>(); |
|||
|
|||
for (int i = 0; i < xData.size(); i++) { |
|||
String time = String.valueOf(xData.get(i)); |
|||
for (Map.Entry<String, List<Object>> e : yDataMap.entrySet()) { |
|||
valueMap |
|||
.computeIfAbsent(time, k -> new HashMap<>()) |
|||
.put(e.getKey(), e.getValue().get(i)); |
|||
} |
|||
} |
|||
|
|||
List<Object> newX = new ArrayList<>(48); |
|||
Map<String, List<Object>> newY = new HashMap<>(); |
|||
|
|||
for (int i = 0; i < 48; i++) { |
|||
LocalDateTime t = start.plusMinutes(i * 30); |
|||
String key = t.format(INPUT_FMT); |
|||
newX.add(key); |
|||
|
|||
Map<String, Object> seriesValues = valueMap.get(key); |
|||
for (String series : yDataMap.keySet()) { |
|||
newY |
|||
.computeIfAbsent(series, k -> new ArrayList<>()) |
|||
.add(seriesValues == null ? null : seriesValues.get(series)); |
|||
} |
|||
} |
|||
|
|||
lineData.setXData(newX); |
|||
lineData.setYData(newY); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 给计测设备,按半小时聚合数据,求平均值 |
|||
* 00~29 分 → HH:00:00 |
|||
* 30~59 分 → HH:30:00 |
|||
*/ |
|||
public static void aggregateAverageByHalfHour(LineData lineData) { |
|||
|
|||
List<Object> xData = lineData.getXData(); |
|||
Map<String, List<Object>> yDataMap = lineData.getYData(); |
|||
|
|||
if (xData == null || yDataMap == null) { |
|||
return; |
|||
} |
|||
|
|||
Map<String, Map<String, List<Double>>> halfHourMap = new TreeMap<>(); |
|||
|
|||
for (int i = 0; i < xData.size(); i++) { |
|||
LocalDateTime time = LocalDateTime.parse(String.valueOf(xData.get(i)), INPUT_FMT); |
|||
|
|||
int minute = time.getMinute() < 30 ? 0 : 30; |
|||
LocalDateTime halfHourTime = time.withMinute(minute).withSecond(0).withNano(0); |
|||
String key = halfHourTime.format(INPUT_FMT); |
|||
|
|||
for (Map.Entry<String, List<Object>> e : yDataMap.entrySet()) { |
|||
Object yVal = e.getValue().get(i); |
|||
if (yVal == null) continue; |
|||
|
|||
halfHourMap |
|||
.computeIfAbsent(key, k -> new HashMap<>()) |
|||
.computeIfAbsent(e.getKey(), k -> new ArrayList<>()) |
|||
.add(Double.parseDouble(String.valueOf(yVal))); |
|||
} |
|||
} |
|||
|
|||
List<Object> newX = new ArrayList<>(); |
|||
Map<String, List<Object>> newY = new HashMap<>(); |
|||
|
|||
for (Map.Entry<String, Map<String, List<Double>>> entry : halfHourMap.entrySet()) { |
|||
newX.add(entry.getKey()); |
|||
|
|||
for (Map.Entry<String, List<Double>> e : entry.getValue().entrySet()) { |
|||
double avg = e.getValue().stream().mapToDouble(Double::doubleValue).average().orElse(0); |
|||
newY.computeIfAbsent(e.getKey(), k -> new ArrayList<>()).add(avg); |
|||
} |
|||
} |
|||
|
|||
lineData.setXData(newX); |
|||
lineData.setYData(newY); |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 按半小时聚合,只保留每个半小时内的最后一条数据 |
|||
*/ |
|||
public static void aggregateLastByHalfHour(LineData lineData) { |
|||
|
|||
List<Object> xData = lineData.getXData(); |
|||
Map<String, List<Object>> yDataMap = lineData.getYData(); |
|||
|
|||
if (xData == null || yDataMap == null) { |
|||
return; |
|||
} |
|||
|
|||
Map<String, Map<String, Object>> halfHourLastMap = new TreeMap<>(); |
|||
|
|||
for (int i = 0; i < xData.size(); i++) { |
|||
LocalDateTime time = LocalDateTime.parse(String.valueOf(xData.get(i)), INPUT_FMT); |
|||
|
|||
int minute = time.getMinute() < 30 ? 0 : 30; |
|||
LocalDateTime halfHourTime = time.withMinute(minute).withSecond(0).withNano(0); |
|||
String key = halfHourTime.format(INPUT_FMT); |
|||
|
|||
for (Map.Entry<String, List<Object>> e : yDataMap.entrySet()) { |
|||
Object yVal = e.getValue().get(i); |
|||
if (yVal == null) continue; |
|||
|
|||
halfHourLastMap |
|||
.computeIfAbsent(key, k -> new HashMap<>()) |
|||
.put(e.getKey(), yVal); |
|||
} |
|||
} |
|||
|
|||
List<Object> newX = new ArrayList<>(); |
|||
Map<String, List<Object>> newY = new HashMap<>(); |
|||
|
|||
for (Map.Entry<String, Map<String, Object>> entry : halfHourLastMap.entrySet()) { |
|||
newX.add(entry.getKey()); |
|||
|
|||
for (Map.Entry<String, Object> e : entry.getValue().entrySet()) { |
|||
newY.computeIfAbsent(e.getKey(), k -> new ArrayList<>()).add(e.getValue()); |
|||
} |
|||
} |
|||
|
|||
lineData.setXData(newX); |
|||
lineData.setYData(newY); |
|||
} |
|||
|
|||
} |
|||
|
|||
Loading…
Reference in new issue