从DB获取列表并合并列表中的公共字段



我有一个如下列表:-

List<ScheduleActionDispatchDTO> pendingScheduleActions 
=restClientApi.getPendingSchedules();

上面的列表来自DB,其值如下-

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_utcend_time_utc的任何行值是相同的,然后合并这些行的request_json的值在一起。

应该变成-

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"}]'

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"}'

I tried this -

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.getUserUd(), s.getStartTimeUtc(), s.getEndTimeUtc()),
s -> s));
// iterate and combine but not sure how
}

可以这样做。我假设您有如下形式的1记录:

public record PendingScheduleAction(
long scheduleRequestId,
int userId,
LocalDateTime startTimeUtc,
LocalDateTime endTimeUtc,
String requestJson
) { }

我们可以首先创建一个Merger,它被用作分组键。我们添加了一个ofPendingScheduleAction方法,这是一个方便的方法来简化分组。我们还添加了一个merge方法,它可以合并两个PendingScheduleAction对象。

record Merger(long scheduleRequestId, int userId, LocalDateTime startTimeUtc, LocalDateTime endTimeUtc) {
public static Merger ofPendingScheduleAction(PendingScheduleAction action) {
return new Merger(action.scheduleRequestId(), action.userId(), action.startTimeUtc(), action.endTimeUtc());
}
private static PendingScheduleAction merge(PendingScheduleAction a, PendingScheduleAction b) {
String json = a.requestJson() + '' + b.requestJson();
return new PendingScheduleAction(a.scheduleRequestId(), a.userId(), a.startTimeUtc(), a.endTimeUtc(), json);
}
}

现在你可以利用groupingBy,reducingcollectingAndThen来达到预期的结果:

list.stream()
.collect(groupingBy(Merger::ofPendingScheduleAction, collectingAndThen(reducing(Merger::merge), optional -> {
var entry = optional.orElseThrow();
String[] jsonLines = entry.requestJson().split("");
String json = (jsonLines.length == 1 ? jsonLines[0] : "[" + String.join(",", jsonLines) + "]");
return new PendingScheduleAction(entry.scheduleRequestId(), entry.userId(), entry.startTimeUtc(), entry.endTimeUtc(), json);
})));

这里发生的是,我们首先定义PendingScheduleAction实例如何分组。Javadocs将其称为分类器。现在你说的"这样,如果schedule_request_id,user_id,start_time_utcend_time_utc的任何行值是相同的,然后合并">,所以我们需要把这些属性一起到一个对象。Merger类执行此操作。

Collectors.reducing(Merger::merge)取一个组的所有对象,并使用Merger::merge方法合并它们。由于reducing返回一个Optional,我们需要解包它(用orElseThrow),但我们还需要修复JSON,因为我们临时用NUL字节连接它。

那么结果是一个Map<Merger, PendingScheduleAction>,您可以调用values()来获得合并值的列表。


注意事项:

  • 我使用NUL字节暂时分离不同的JSON部分(这有点黑客)。这是由于您的需求,您希望多个合并的JSON条目在JSON数组中,但单个条目没有数组。我建议您将所有JSON条目放入数组中,而不管条目的数量(可能是1)。这既更容易解析也更容易处理。

    您可以将上述代码中的所有替换为,,并且collectingAndThen方法的结束器函数看起来像这样:

    var entry = optional.orElseThrow();
    return new PendingScheduleAction(entry.scheduleRequestId(), entry.userId(), entry.startTimeUtc(), entry.endTimeUtc(), "[" + entry.requestJson() + "]");
    

  • 您的开始时间和结束时间建议它们是UTC时间戳,但日期字符串显示的是本地时间。我认为你的时间戳应该看起来像这样:2022-12-16T21:00:00Z.


1如果您没有访问记录特性的权限,您可以使用以下命令轻松地模拟它们:

public class PendingScheduleAction {
private long scheduleRequestId;
private int userId;
private LocalDateTime startTimeUtc;
private LocalDateTime endTimeUtc;
private String requestJson;
// Canonical all-args constructor
public PendingScheduleAction(long scheduleRequestId, int userId, LocalDateTime startTimeUtc, LocalDateTime endTimeUtc, String requestJson) {
this.scheduleRequestId = scheduleRequestId;
this.userId = userId;
this.startTimeUtc = startTimeUtc;
this.endTimeUtc = endTimeUtc;
this.requestJson = requestJson;
}
// Record-style getter (just the name of the field, not starting with 'get'
public long scheduleRequestId() {
return scheduleRequestId;
}
// And the remaining getters
public boolean equals(Object o) {
// A proper equals implementation.
// Don't forget hashCode()
}
}

您还可以使用Lombok用@AllArgsConstructor@Getter@EqualsAndHashCode注释类。

相关内容

  • 没有找到相关文章

最新更新