如何合并DB获取的ScheduleActionDispatchDTO列表同项的request_json
问题描述
从数据库获取待处理调度列表:
List<ScheduleActionDispatchDTO> pendingScheduleActions = restClientApi.getPendingSchedules();
数据示例
schedule_request_id = 576, user_id = 24, start_time_utc = '2022-12-16 21:00:00', end_time_utc = '2022-12-17 01:00:00', request_json = '{"testId": "5", "grade": "A"}' schedule_request_id = 576, user_id = 24, start_time_utc = '2022-12-16 21:00:00', end_time_utc = '2022-12-17 01:00:00', request_json = '{"subjectId": "10", "name": "dictation"}' schedule_request_id = 577, user_id = 24, start_time_utc = '2022-12-17 21:00:00', end_time_utc = '2022-12-18 01:00:00', request_json = '{"testId": "5", "grade": "A"}'
需求
当列表中任意行的schedule_request_id、user_id、start_time_utc和end_time_utc字段值完全相同时,将这些行的request_json值合并。合并后的预期结果如下:
合并结果1
schedule_request_id = 576, user_id = 24, start_time_utc = '2022-12-16 21:00:00', end_time_utc = '2022-12-17 01:00:00', combinedResult = '[{"testId": "5", "grade": "A"}, {"subjectId": "10", "name": "dictation"}]'
合并结果2
schedule_request_id = 577, user_id = 24, start_time_utc = '2022-12-17 21:00:00', end_time_utc = '2022-12-18 01:00:00', combinedResult = '{"testId": "5", "grade": "A"}'
已尝试的代码
目前完成了初步分组,但不清楚后续合并逻辑:
Map<Long, List<ScheduleActionDispatchDTO>> requestMap = pendingScheduleActions.stream() .collect(Collectors.groupingBy( ScheduleActionDispatchDTO::getScheduleRequestId, Collectors.toList())); for (Map.Entry<Long, List<ScheduleActionDispatchDTO>> entry : requestMap.entrySet()) { List<ScheduleActionDispatchDTO> sameRequestActions = entry.getValue(); Map<ScheduleActionDispatchPair, ScheduleActionDispatchDTO> schedulePairAction = sameRequestActions.stream(). collect(Collectors.toMap( s -> new ScheduleActionDispatchPair(s.getScheduleRequestId(), s.getUserId(), s.getStartTimeUtc(), s.getEndTimeUtc()), s -> s)); // 不知道如何继续完成合并 }
解决方案
步骤1:确保分组键的正确性
首先要保证ScheduleActionDispatchPair类正确重写了equals()和hashCode()方法,让schedule_request_id、user_id、start_time_utc、end_time_utc四个字段都参与相等性判断,这样才能作为Map的键实现正确分组。
步骤2:直接按完整条件分组
无需先按schedule_request_id拆分,直接用ScheduleActionDispatchPair作为分组键,一步完成同条件数据的聚合:
// 按四个字段分组,每组是符合条件的DTO列表 Map<ScheduleActionDispatchPair, List<ScheduleActionDispatchDTO>> groupedByKey = pendingScheduleActions.stream() .collect(Collectors.groupingBy( s -> new ScheduleActionDispatchPair( s.getScheduleRequestId(), s.getUserId(), s.getStartTimeUtc(), s.getEndTimeUtc() ) ));
步骤3:合并request_json并生成结果
遍历分组后的Map,借助JSON工具类(如Jackson或Gson)解析和生成JSON,避免手动拼接出错:
示例代码(使用Jackson)
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; ObjectMapper objectMapper = new ObjectMapper(); List<Map<String, Object>> finalResults = new ArrayList<>(); for (Map.Entry<ScheduleActionDispatchPair, List<ScheduleActionDispatchDTO>> entry : groupedByKey.entrySet()) { ScheduleActionDispatchPair key = entry.getKey(); List<ScheduleActionDispatchDTO> dtoList = entry.getValue(); // 解析所有request_json为对象 List<Object> jsonItems = new ArrayList<>(); for (ScheduleActionDispatchDTO dto : dtoList) { try { Map<String, Object> jsonObj = objectMapper.readValue(dto.getRequestJson(), new TypeReference<>() {}); jsonItems.add(jsonObj); } catch (Exception e) { // 处理JSON解析异常 e.printStackTrace(); } } // 生成合并后的JSON字符串 String combinedResult; if (jsonItems.size() == 1) { // 单条数据直接输出原格式 try { combinedResult = objectMapper.writeValueAsString(jsonItems.get(0)); } catch (Exception e) { combinedResult = dtoList.get(0).getRequestJson(); } } else { // 多条数据生成JSON数组 try { combinedResult = objectMapper.writeValueAsString(jsonItems); } catch (Exception e) { combinedResult = "[]"; } } // 组装结果(可按需转为自定义DTO) Map<String, Object> result = new HashMap<>(); result.put("schedule_request_id", key.getScheduleRequestId()); result.put("user_id", key.getUserId()); result.put("start_time_utc", key.getStartTimeUtc()); result.put("end_time_utc", key.getEndTimeUtc()); result.put("combinedResult", combinedResult); finalResults.add(result); }
步骤4:可选 - 封装为自定义DTO
如果需要结构化结果,可以创建CombinedScheduleResultDTO类,替换上述的Map<String, Object>:
public class CombinedScheduleResultDTO { private Long scheduleRequestId; private Long userId; private String startTimeUtc; private String endTimeUtc; private String combinedResult; // 构造方法、getter、setter }
然后在循环中创建DTO实例:
CombinedScheduleResultDTO resultDTO = new CombinedScheduleResultDTO(); resultDTO.setScheduleRequestId(key.getScheduleRequestId()); resultDTO.setUserId(key.getUserId()); resultDTO.setStartTimeUtc(key.getStartTimeUtc()); resultDTO.setEndTimeUtc(key.getEndTimeUtc()); resultDTO.setCombinedResult(combinedResult); finalResults.add(resultDTO);
内容的提问来源于stack exchange,提问作者sjain
相关产品推荐
相关产品推荐

