【发布时间】:2021-09-21 21:49:35
【问题描述】:
通常这种类型的算法是使用 SQL(间隙和孤岛)完成的,但我需要找到一种方法在 Java 中完成。
我有一组对象:Set<UnavailableBlock>
UnavailableBlock 类如下(简化):
@Getter
@Setter
@AllArgsConstructor
@ToString
public class UnavailableBlock{
OffsetDateTime blockStartTime;
OffsetDateTime blockEndTime;
}
允许重叠间隔,所以我试图返回一个Set<UnavailableBlock>,但合并的间隔在它们之间留下了各自的间隙。我正在使用 OffsetDateTime 并且需要考虑时间。
例如(使用 Outlook):
private Set<AppointmentAvailabilityBlock> mergeUnavailabilitiesBlocks(
Set<AppointmentAvailabilityBlock> appointmentComponentUnavailabilitiesBlock) {
// Transform Set to List
List<AppointmentAvailabilityBlock> intervals = new LinkedList<AppointmentAvailabilityBlock>();
intervals.addAll(appointmentComponentUnavailabilitiesBlock);
// Sort by blockStartTime
intervals.sort(Comparator.comparing(AppointmentAvailabilityBlock::getBlockStartTime));
// Merge
LinkedList<AppointmentAvailabilityBlock> merged = new LinkedList<>();
for (AppointmentAvailabilityBlock interval : intervals) {
// No overlap with the previous interval, append it.
if (merged.isEmpty() || merged.getLast().getBlockEndTime().isBefore(interval.getBlockStartTime())) {
merged.add(interval);
} else { // There is overlap
OffsetDateTime maxOffsetDateTime = merged.getLast().getBlockEndTime().isAfter(
interval.getBlockEndTime()) ? merged.getLast().getBlockEndTime() : interval.getBlockEndTime();
merged.getLast().setBlockEndTime(maxOffsetDateTime);
}
}
return new HashSet<AppointmentAvailabilityBlock>(merged);
}
问题是我不断得到重叠的块:
橙色 = 合并前
绿色 = 合并后
注意:我正在使用带有 lombok 注释的 Spring Boot
【问题讨论】:
-
首先将 UnavailableBlock 从 Set 移动到某个有序结构(列表、数组、...)。然后按 blockStartTime 对它们进行排序。最后去 trought 排序的 blockStartTime 列表,如果两个相邻记录相互重叠,则用合并的记录替换它们。
-
谢谢@MartinDendis。我已经添加了我的代码并解释了为什么我仍在为合并而苦苦挣扎。
-
TBH 我在您的代码中找不到任何缺陷,并且从我的简短测试中它可以工作。能否提供一些示例测试数据?
-
我直接从我的数据库中提取了数百条随机行。我将尝试编译一组示例。问题可能是因为我的数据是随机的
标签: java datetime merge overlap gaps-and-islands