package com.sckj.iron.service.impl; import com.sckj.common.util.TimeUtils; import com.sckj.iron.dto.IronTrendL1DTO; import com.sckj.iron.dto.IronTrendL2DTO; import com.sckj.iron.dto.RealtimeData; import com.sckj.l2.dto.TrendRequest; import com.sckj.l2.entity.TL2Data; import com.sckj.l2.service.impl.TL2DataServiceImpl; import com.sckj.opc.entity.OPCData; import com.sckj.opc.service.OPCDataServiceImpl; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.text.SimpleDateFormat; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; @Slf4j @Service public class TIronVisualScreenServiceImpl { @Resource OPCDataServiceImpl opcDataService; @Resource TL2DataServiceImpl tl2DataService; private static final SimpleDateFormat sdfMinute = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:00"); /*** * 实时数据图图例 * @param ironChart * @return */ public synchronized Map getIronLegend(Map ironChart, int ironPasstime) { Map result = new LinkedHashMap<>(); if (ObjectUtils.isEmpty(ironChart)) { return result; } // 1. 计算起止时间 int hours = 24; //给固定时间,24小时之内 java.util.Date endTime = new java.util.Date(); java.util.Calendar cal = java.util.Calendar.getInstance(); cal.setTime(endTime); cal.add(java.util.Calendar.HOUR_OF_DAY, -hours); java.util.Date startTime = cal.getTime(); // // 1. 计算起止时间 // // 临时调试用,固定时间范围 // final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // final java.util.Date startTime; // final java.util.Date endTime; // try { // startTime = sdf.parse("2025-07-13 02:15:00"); // endTime = sdf.parse("2025-07-14 00:20:00"); // } catch (Exception e) { // throw new RuntimeException("时间解析失败", e); // } List tl2DataList = tl2DataService.lambdaQuery() .between(TL2Data::getIronStarttime, new SimpleDateFormat("yyyyMMddHHmmss").format(startTime), new SimpleDateFormat("yyyyMMddHHmmss").format(endTime)) .eq(TL2Data::getTapholeId, "1") .orderByAsc(TL2Data::getIronStarttime) .list(); List> elementS = (List>) ironChart.get("elementS"); List> elementSi = (List>) ironChart.get("elementSi"); List> mudWeight = (List>) ironChart.get("mudWeight"); List> pollMm = (List>) ironChart.get("pollMm"); List> openDepth = (List>) ironChart.get("openDepth"); List> ironCosttime = (List>) ironChart.get("ironCosttime"); List> ironSpeed = (List>) ironChart.get("ironSpeed"); List> ironTemp = (List>) ironChart.get("ironTemp"); List> ironWeight = (List>) ironChart.get("ironWeight"); result.put("elementS", RealtimeData.builder().desc("铁水成分-硫").value(elementS.get(elementS.size() - 1).get(1)).build()); result.put("elementSi", RealtimeData.builder().desc("铁水成分-硅").value(elementSi.get(elementSi.size() - 1).get(1)).build()); result.put("mudWeight", RealtimeData.builder().desc("打泥量").value(mudWeight.get(mudWeight.size() - 1).get(1)).unit("L").build()); result.put("pollMm", RealtimeData.builder().desc("钻杆直径").value(pollMm.get(pollMm.size() - 1).get(1)).unit("mm").build()); result.put("openDepth", RealtimeData.builder().desc("开口深度").value(openDepth.get(openDepth.size() - 1).get(1)).unit("mm").build()); RealtimeData realtimeDataIronConsttime = RealtimeData.builder().desc("出铁时间").unit("min").value(ironPasstime).build(); if (ObjectUtils.isNotEmpty(tl2DataList)) { List>> collect = tl2DataList.stream().map(item -> { List> mapList = new ArrayList<>(); Map map = new HashMap<>(); map.put("name", String.format("第%s次出铁\n(%s号铁口)%s分钟", item.getIronNo(), item.getTapholeId(), item.getIronCosttime())); map.put("xAxis", TimeUtils.formatPartialDateString(item.getIronStarttime())); mapList.add(map); map = new HashMap<>(); map.put("xAxis", TimeUtils.formatPartialDateString(item.getIronEndtime())); mapList.add(map); return mapList; }).collect(Collectors.toList()); Map extraMap = new HashMap<>(); extraMap.put("mark", collect); realtimeDataIronConsttime.setExtra(extraMap); } result.put("ironCosttime", realtimeDataIronConsttime); result.put("ironWeight", RealtimeData.builder().desc("累计出铁量").value(ironWeight.get(ironWeight.size() - 1).get(1)).unit("t").build()); result.put("ironSpeed", RealtimeData.builder().desc("铁水流速").value(ironSpeed.get(ironSpeed.size() - 1).get(1)).unit("t/min").build()); result.put("ironTemp", RealtimeData.builder().desc("铁水温度").value(ironTemp.get(ironTemp.size() - 1).get(1)).unit("℃").build()); return result; } /*** * 实时折线图数据, * BF4_1_IRONNOTCH_TAPPING表示出铁状态,数值只有0和1,1表示正在出铁,0表示未出铁 * BF4_1TH_1_MIR_NWT表示四高炉1TH-1号车铁水净重,BF4_1TH_2_MIR_NWT表示四高炉1TH-2号车铁水净重,这2车一开始的重量为0,然后装入铁水重量不断增加,直到满载,然后减为0,然后继续增加,以此往复 * * @param queryDateType * @return */ public synchronized Map getIronChart(TrendRequest queryDateType) { // 1. 计算起止时间 int hours = Objects.isNull(queryDateType.getQueryHourBefore()) ? 24 : queryDateType.getQueryHourBefore(); //给固定时间,24小时之内 java.util.Date endTime = new java.util.Date(); java.util.Calendar cal = java.util.Calendar.getInstance(); cal.setTime(endTime); cal.add(java.util.Calendar.HOUR_OF_DAY, -hours); java.util.Date startTime = cal.getTime(); // 临时调试用,固定时间范围 // final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // final java.util.Date startTime; // final java.util.Date endTime; // try { // startTime = sdf.parse("2025-07-19 09:30:00"); // endTime = sdf.parse("2025-07-20 09:30:00"); // } catch (Exception e) { // throw new RuntimeException("时间解析失败", e); // } // 2. 异步查询所有数据 CompletableFuture> opcDataFuture = CompletableFuture.supplyAsync(() -> opcDataService.lambdaQuery() .in(OPCData::getPointName, Arrays.asList( "BF4_1_IRONNOTCH_MIR_TEMP", // 温度 "BF4_1_IRONNOTCH_RAILLINE_ACPIRON_SPEED1", // 1车流速 "BF4_1_IRONNOTCH_RAILLINE_ACPIRON_SPEED2", // 2车流速 "BF4_1TH_1_MIR_NWT", // 四高炉1TH-1号车铁水净重 "BF4_1TH_2_MIR_NWT", // 四高炉1TH-2号车铁水净重 "BF4_1_IRONNOTCH_TAPPING", // 1号铁口出铁状态 "BF4_1TH_2_TPC_CARNO", // 1TH-2号车混铁车车号 "BF4_1TH_1_TPC_CARNO" // 1TH-1号车混铁车车号 )) .between(OPCData::getServerTime, startTime, endTime) .orderByAsc(OPCData::getServerTime) .list() ); CompletableFuture> l2DataFuture = CompletableFuture.supplyAsync(() -> tl2DataService.lambdaQuery() .between(TL2Data::getIronStarttime, new SimpleDateFormat("yyyyMMddHHmmss").format(startTime), new SimpleDateFormat("yyyyMMddHHmmss").format(endTime)) .eq(TL2Data::getTapholeId, "1") .orderByAsc(TL2Data::getIronStarttime) .list() ); // 3. 等待所有查询完成并转换数据 try { // 4. 按pointName分类OPC数据并转换为DTO Map> opcDataMap = opcDataFuture.get().stream() .collect(Collectors.groupingBy(OPCData::getPointName)); List l2DataList = l2DataFuture.get(); // 并行转换所有数据 //铁水温度 CompletableFuture> tempListFuture = CompletableFuture.supplyAsync(() -> opcDataMap.getOrDefault("BF4_1_IRONNOTCH_MIR_TEMP", new ArrayList<>()) .stream().map(item -> { IronTrendL1DTO dto = new IronTrendL1DTO(); dto.setData(item.getData()); dto.setCreateTime(item.getSourceTime()); return dto; }).collect(Collectors.toList()) ); //1TH-1号车受铁速度 CompletableFuture> speed1ListFuture = CompletableFuture.supplyAsync(() -> opcDataMap.getOrDefault("BF4_1_IRONNOTCH_RAILLINE_ACPIRON_SPEED1", new ArrayList<>()) .stream().map(item -> { IronTrendL1DTO dto = new IronTrendL1DTO(); dto.setData(item.getData()); dto.setCreateTime(item.getSourceTime()); return dto; }).collect(Collectors.toList()) ); //1TH-2号车受铁速度 CompletableFuture> speed2ListFuture = CompletableFuture.supplyAsync(() -> opcDataMap.getOrDefault("BF4_1_IRONNOTCH_RAILLINE_ACPIRON_SPEED2", new ArrayList<>()) .stream().map(item -> { IronTrendL1DTO dto = new IronTrendL1DTO(); dto.setData(item.getData()); dto.setCreateTime(item.getSourceTime()); return dto; }).collect(Collectors.toList()) ); //BF4_1TH_1_MIR_NWT 1号车净重 CompletableFuture> weight1ListFuture = CompletableFuture.supplyAsync(() -> opcDataMap.getOrDefault("BF4_1TH_1_MIR_NWT", new ArrayList<>()) .stream().map(item -> { IronTrendL1DTO dto = new IronTrendL1DTO(); dto.setData(item.getData()); dto.setCreateTime(item.getSourceTime()); return dto; }).collect(Collectors.toList()) ); //BF4_1TH_2_MIR_NWT 2号车净重 CompletableFuture> weight2ListFuture = CompletableFuture.supplyAsync(() -> opcDataMap.getOrDefault("BF4_1TH_2_MIR_NWT", new ArrayList<>()) .stream().map(item -> { IronTrendL1DTO dto = new IronTrendL1DTO(); dto.setData(item.getData()); dto.setCreateTime(item.getSourceTime()); return dto; }).collect(Collectors.toList()) ); //L2 CompletableFuture> elemenListFuture = CompletableFuture.supplyAsync(() -> l2DataList.stream().map(item -> { IronTrendL2DTO dto = new IronTrendL2DTO(); try { dto.setElementS(item.getElementS() != null ? Double.parseDouble(item.getElementS()) : null); } catch (NumberFormatException e) { dto.setElementS(null); } try { dto.setElementSi(item.getElementSi() != null ? Double.parseDouble(item.getElementSi()) : null); } catch (NumberFormatException e) { dto.setElementSi(null); } dto.setIronStarttime(item.getIronStarttime()); dto.setIronEndtime(item.getIronEndtime()); dto.setPollMm(item.getPollMm()); dto.setOpenDepth(item.getOpenDepth()); dto.setMudWeight(item.getMudWeight()); dto.setIronCosttime(item.getIronCosttime()); return dto; }).collect(Collectors.toList()) ); // 等待所有转换完成 CompletableFuture.allOf( tempListFuture, speed1ListFuture, speed2ListFuture, weight1ListFuture, weight2ListFuture, elemenListFuture ).join(); // 5. 封装返回 List tempList = tempListFuture.get(); List speed1List = speed1ListFuture.get(); List speed2List = speed2ListFuture.get(); List weight1List = weight1ListFuture.get(); List weight2List = weight2ListFuture.get(); List elemenList = elemenListFuture.get(); // 1. 生成完整的每一分钟时间点 java.util.List xAxis = new java.util.ArrayList<>(); java.util.Calendar cursor = java.util.Calendar.getInstance(); cursor.setTime(startTime); while (!cursor.getTime().after(endTime)) { xAxis.add(sdfMinute.format(cursor.getTime())); cursor.add(java.util.Calendar.MINUTE, 1); } // 查询区间前的最近一条历史数据(前置值) // OPC类 OPCData preTemp = opcDataService.lambdaQuery() .eq(OPCData::getPointName, "BF4_1_IRONNOTCH_MIR_TEMP") .isNotNull(OPCData::getData) .lt(OPCData::getServerTime, startTime) .orderByDesc(OPCData::getServerTime) .last("limit 1").one(); OPCData preSpeed1 = opcDataService.lambdaQuery() .eq(OPCData::getPointName, "BF4_1_IRONNOTCH_RAILLINE_ACPIRON_SPEED1") .isNotNull(OPCData::getData) .lt(OPCData::getServerTime, startTime) .orderByDesc(OPCData::getServerTime) .last("limit 1").one(); OPCData preSpeed2 = opcDataService.lambdaQuery() .eq(OPCData::getPointName, "BF4_1_IRONNOTCH_RAILLINE_ACPIRON_SPEED2") .isNotNull(OPCData::getData) .lt(OPCData::getServerTime, startTime) .orderByDesc(OPCData::getServerTime) .last("limit 1").one(); OPCData preWeight1 = opcDataService.lambdaQuery() .eq(OPCData::getPointName, "BF4_1TH_1_MIR_NWT") .isNotNull(OPCData::getData) .lt(OPCData::getServerTime, startTime) .orderByDesc(OPCData::getServerTime) .last("limit 1").one(); OPCData preWeight2 = opcDataService.lambdaQuery() .eq(OPCData::getPointName, "BF4_1TH_2_MIR_NWT") .isNotNull(OPCData::getData) .lt(OPCData::getServerTime, startTime) .orderByDesc(OPCData::getServerTime) .last("limit 1").one(); // tappingMap补齐每一分钟,前面无数据用前置值补齐 // 先查区间前最近一条tapping Integer preTappingVal = 0; OPCData preTapping = opcDataService.lambdaQuery() .eq(OPCData::getPointName, "BF4_1_IRONNOTCH_TAPPING") .isNotNull(OPCData::getData) .lt(OPCData::getServerTime, startTime) .orderByDesc(OPCData::getServerTime) .last("limit 1").one(); // L2类 TL2Data preL2 = tl2DataService.lambdaQuery() .lt(TL2Data::getIronStarttime, new SimpleDateFormat("yyyyMMddHHmmss").format(startTime)) .eq(TL2Data::getTapholeId, "1") .orderByDesc(TL2Data::getIronStarttime) .last("limit 1").one(); // 2. 构建每分钟补全的二维数组 java.util.Map result = new java.util.LinkedHashMap<>(); // if (preTapping != null && preTapping.getData() != null) { Object v = preTapping.getData(); if (v instanceof Number) preTappingVal = ((Number) v).intValue(); else if (v instanceof String) { String str = ((String) v).trim(); if (!str.isEmpty()) { try { preTappingVal = Integer.parseInt(str); } catch (Exception ignore) { } } } } // 构建每分钟tappingMap Map tappingMap = new LinkedHashMap<>(); List tappingList = opcDataMap.getOrDefault("BF4_1_IRONNOTCH_TAPPING", new ArrayList<>()); Map rawTappingMap = new LinkedHashMap<>(); for (OPCData item : tappingList) { if (item.getServerTime() != null && item.getData() != null) { String min = sdfMinute.format(item.getServerTime()); Integer val = null; Object v = item.getData(); if (v instanceof Number) val = ((Number) v).intValue(); else if (v instanceof String) { String str = ((String) v).trim(); if (!str.isEmpty()) { try { val = Integer.parseInt(str); } catch (Exception ignore) { } } } if (val != null) rawTappingMap.put(min, val); } } Integer last = preTappingVal; for (String t : xAxis) { Integer v = rawTappingMap.getOrDefault(t, last); tappingMap.put(t, v); if (v != null) last = v; } int ironWeightScale = 2; // 可调整为0、1、2等 List> ironFlowArr = buildIronWeightMinuteArray(xAxis, tappingMap, weight1List, weight2List, ironWeightScale); result.put("ironWeight", ironFlowArr); // 处理铁水流速,出铁中按原逻辑,出铁结束后为0 List> ironSpeedArr = buildMinuteArrayForSpeed(xAxis, speed1List, speed2List, tappingMap); List> ironTempArr = buildMinuteArray(tempList, xAxis, preTemp != null ? preTemp.getData() : null); for (int i = 0; i < xAxis.size(); i++) { String t = xAxis.get(i); Integer tapping = tappingMap.getOrDefault(t, 0); if (tapping == 0 && ironSpeedArr.get(i).size() > 1) { ironSpeedArr.get(i).set(1, 0); ironTempArr.get(i).set(1, 0); } } result.put("ironSpeed", ironSpeedArr); result.put("ironTemp", ironTempArr); // 处理L2类数据,tapping=0时设为0 List> elementSArr = buildL2MinuteArray(elemenList, xAxis, tappingMap, "elementS", preL2 != null ? preL2.getElementS() : null); List> elementSiArr = buildL2MinuteArray(elemenList, xAxis, tappingMap, "elementSi", preL2 != null ? preL2.getElementSi() : null); List> mudWeightArr = buildL2MinuteArray(elemenList, xAxis, tappingMap, "mudWeight", preL2 != null ? preL2.getMudWeight() : null); List> pollMmArr = buildL2MinuteArray(elemenList, xAxis, tappingMap, "pollMm", preL2 != null ? preL2.getPollMm() : null); List> openDepthArr = buildL2MinuteArray(elemenList, xAxis, tappingMap, "openDepth", preL2 != null ? preL2.getOpenDepth() : null); List> ironCosttimeArr = buildL2MinuteArray(elemenList, xAxis, tappingMap, "ironCosttime", preL2 != null ? preL2.getIronCosttime() : null); // for (int i = 0; i < xAxis.size(); i++) { // String t = xAxis.get(i); // Integer tapping = tappingMap.getOrDefault(t, 0); // if (tapping == 0) { // if (elementSArr.get(i).size() > 1) elementSArr.get(i).set(1, 0); // if (elementSiArr.get(i).size() > 1) elementSiArr.get(i).set(1, 0); // if (mudWeightArr.get(i).size() > 1) mudWeightArr.get(i).set(1, 0); // if (pollMmArr.get(i).size() > 1) pollMmArr.get(i).set(1, 0); // if (openDepthArr.get(i).size() > 1) openDepthArr.get(i).set(1, 0); // if (ironCosttimeArr.get(i).size() > 1) ironCosttimeArr.get(i).set(1, 0); // } // } result.put("elementS", elementSArr); result.put("elementSi", elementSiArr); result.put("mudWeight", mudWeightArr); result.put("pollMm", pollMmArr); result.put("openDepth", openDepthArr); result.put("ironCosttime", ironCosttimeArr); return result; } catch (Exception e) { e.printStackTrace(); } return null; } // 新增工具方法:L1类型 private java.util.List> buildMinuteArray(java.util.List list, java.util.List xAxis, Object preValue) { java.util.Map timeValueMap = new java.util.LinkedHashMap<>(); for (IronTrendL1DTO e : list) { if (e.getCreateTime() != null) { String min = sdfMinute.format(e.getCreateTime()); timeValueMap.put(min, e.getData()); } } java.util.List> arr = new java.util.ArrayList<>(); Object last = preValue; for (String t : xAxis) { Object v = timeValueMap.getOrDefault(t, last); arr.add(java.util.Arrays.asList(t, v)); if (v != null) last = v; } return arr; } // 铁水流速(重写:合并取最大值,出铁周期内补齐空值,且出铁周期内流速不允许为0) private java.util.List> buildMinuteArrayForSpeed(java.util.List xAxis, java.util.List speed1List, java.util.List speed2List, java.util.Map tappingMap) { java.util.Map speed1Map = new java.util.LinkedHashMap<>(); java.util.Map speed2Map = new java.util.LinkedHashMap<>(); for (IronTrendL1DTO e : speed1List) { if (e.getCreateTime() != null) { String min = sdfMinute.format(e.getCreateTime()); Object v = e.getData(); Double value = null; if (v instanceof Number) value = ((Number) v).doubleValue(); else if (v instanceof String) { try { value = Double.parseDouble((String) v); } catch (Exception ignore) { } } if (value != null) speed1Map.put(min, value); } } for (IronTrendL1DTO e : speed2List) { if (e.getCreateTime() != null) { String min = sdfMinute.format(e.getCreateTime()); Object v = e.getData(); Double value = null; if (v instanceof Number) value = ((Number) v).doubleValue(); else if (v instanceof String) { try { value = Double.parseDouble((String) v); } catch (Exception ignore) { } } if (value != null) speed2Map.put(min, value); } } // 合并为最大值map java.util.Map speedMap = new java.util.LinkedHashMap<>(); for (String key : speed1Map.keySet()) { speedMap.put(key, speed1Map.get(key)); } for (String key : speed2Map.keySet()) { double v2 = speed2Map.get(key); speedMap.put(key, Math.max(speedMap.getOrDefault(key, 0d), v2)); } java.util.List> arr = new java.util.ArrayList<>(); Double last = null; for (String t : xAxis) { Integer tapping = tappingMap.getOrDefault(t, 0); Double v = speedMap.get(t); if (tapping == 1) { if (v == null || v == 0) { // 出铁周期内流速不允许为0,用上一个非0值 v = last != null ? last : 0d; } arr.add(java.util.Arrays.asList(t, v)); if (v != null && v != 0) last = v; } else { arr.add(java.util.Arrays.asList(t, 0)); } } return arr; } //L2 private java.util.List> buildL2MinuteArray(java.util.List list, java.util.List xAxis, Map tappingMap, String field, Object preValue) { java.util.Map timeValueMap = new java.util.LinkedHashMap<>(); for (IronTrendL2DTO e : list) { String startMin = TimeUtils.formatPartialDateStringMin(e.getIronStarttime()); String endMin = TimeUtils.formatPartialDateStringMin(e.getIronEndtime()); if (startMin != null && endMin != null) { Object v = null; switch (field) { case "elementS": v = e.getElementS(); break; case "elementSi": v = e.getElementSi(); break; case "mudWeight": v = e.getMudWeight(); break; case "pollMm": v = e.getPollMm(); break; case "openDepth": v = e.getOpenDepth(); break; case "ironCosttime": v = e.getIronCosttime(); break; } // 定义时间格式 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:00"); // 解析字符串为LocalDateTime对象 LocalDateTime startTime = LocalDateTime.parse(startMin, formatter); LocalDateTime endTime = LocalDateTime.parse(endMin, formatter); // 遍历每一分钟 LocalDateTime currentTime = startTime; while (!currentTime.isAfter(endTime)) { timeValueMap.put(currentTime.format(formatter), v); // 增加一分钟 currentTime = currentTime.plusMinutes(1); } } } java.util.List> arr = new java.util.ArrayList<>(); Object last = preValue; // for (String time : xAxis) { // Integer tapping = tappingMap.getOrDefault(time, 0); // Object v = timeValueMap.getOrDefault(time, last); // double value = Double.parseDouble(v.toString()); // if (tapping == 1) { // if (value == 0 ) { // // // value = last != null ? Double.parseDouble(last.toString()) : 0; // } // arr.add(java.util.Arrays.asList(time,value)); // if (value != 0){ // last = value; // } // } else { // arr.add(java.util.Arrays.asList(time, 0)); // last = 0; // } // } for (String time : xAxis) { Object value = timeValueMap.getOrDefault(time, last); List item = new ArrayList(); item.add(time); Integer tapping = tappingMap.getOrDefault(time, 0); if (tapping == 0) { item.add(0); last = null; } else { if (null == value) { item.add(0); last = null; } else { item.add(value); last = value; } } arr.add(item); } //处理正在出铁的情况 if (tappingMap.getOrDefault(xAxis.get(xAxis.size() - 1), 0) > 0) { //表明正在出铁中 for (int i = xAxis.size() - 1; i >= 0; i--) { Integer tapping = tappingMap.getOrDefault(xAxis.get(i), 0); if (tapping <= 0) { break; } else { if (arr.get(i).size() > 1) arr.get(i).set(1, 0); } } } return arr; } //铁水重量 private List> buildIronWeightMinuteArray(List xAxis, Map tappingMap, List weight1List, List weight2List, int scale) { Map weight1Map = new LinkedHashMap<>(); for (IronTrendL1DTO e : weight1List) { if (e.getCreateTime() != null) { String min = sdfMinute.format(e.getCreateTime()); Object v = e.getData(); Double value = null; if (v instanceof Number) value = ((Number) v).doubleValue(); else if (v instanceof String) { String str = ((String) v).trim(); if (!str.isEmpty()) { try { value = Double.parseDouble(str); } catch (Exception ignore) { } } } if (value != null) { weight1Map.put(min, value); } } } Map weight2Map = new LinkedHashMap<>(); for (IronTrendL1DTO e : weight2List) { if (e.getCreateTime() != null) { String min = sdfMinute.format(e.getCreateTime()); Object v = e.getData(); Double value = null; if (v instanceof Number) value = ((Number) v).doubleValue(); else if (v instanceof String) { String str = ((String) v).trim(); if (!str.isEmpty()) { try { value = Double.parseDouble(str); } catch (Exception ignore) { } } } if (value != null) { weight2Map.put(min, value); } } } // 合并weight1Map和weight2Map到weightMap,取最大值 Map weightMap = new LinkedHashMap<>(); for (Map.Entry entry : weight1Map.entrySet()) { weightMap.put(entry.getKey(), entry.getValue()); } for (Map.Entry entry : weight2Map.entrySet()) { weightMap.put(entry.getKey(), Math.max(weightMap.getOrDefault(entry.getKey(), 0d), entry.getValue())); } // 按key正序排序 weightMap = weightMap.entrySet().stream() .sorted(Map.Entry.comparingByKey()) .collect(java.util.LinkedHashMap::new, (m, e) -> m.put(e.getKey(), e.getValue()), java.util.LinkedHashMap::putAll); List> arr = new ArrayList<>(); boolean inTappingCycle = false; java.math.BigDecimal cycleTotal = java.math.BigDecimal.ZERO; java.math.BigDecimal lastW = java.math.BigDecimal.ZERO; for (int i = 0; i < xAxis.size(); i++) { String time = xAxis.get(i); Integer tapping = tappingMap.getOrDefault(time, 0); java.math.BigDecimal w = new java.math.BigDecimal(weightMap.getOrDefault(time, 0d).toString()); if (tapping == 1) { if (!inTappingCycle) { inTappingCycle = true; //System.out.println("[出铁周期结束] 开始于: " + time); } if (w.compareTo(java.math.BigDecimal.ZERO) == 0) { w = lastW; weightMap.put(time, w.doubleValue()); } else { lastW = w; } if (i > 0) { java.math.BigDecimal prevW = new java.math.BigDecimal(weightMap.getOrDefault(xAxis.get(i - 1), 0d).toString()); //上一个减去当前的 if (prevW.subtract(w).compareTo(new java.math.BigDecimal("130")) > 0) { //System.out.println("[出铁周期满载情况] 时间: " + xAxis.get(i - 1) + ", 铁水满载值: " + prevW); cycleTotal = cycleTotal.add(prevW); } } arr.add(java.util.Arrays.asList(time, w.add(cycleTotal).setScale(scale, java.math.RoundingMode.HALF_UP).doubleValue())); } else { if (inTappingCycle) { double value = cycleTotal.setScale(scale, java.math.RoundingMode.HALF_UP).doubleValue(); //System.out.println("[出铁周期结束] 结束于: " + time + ", 本周期铁水总净重: " + value); arr.add(java.util.Arrays.asList(time, value)); inTappingCycle = false; cycleTotal = java.math.BigDecimal.ZERO; // for (List objects : arr) { // System.out.println(objects.get(0)+" >>> "+objects.get(1)); // } } else { arr.add(java.util.Arrays.asList(time, 0)); } } } return arr; } }