【问题标题】:Java merge overlapping date intervalsJava合并重叠日期间隔
【发布时间】: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


【解决方案1】:
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);
}

【讨论】:

    猜你喜欢
    • 2011-02-03
    • 1970-01-01
    • 2021-09-03
    • 1970-01-01
    • 1970-01-01
    • 2019-04-12
    • 2014-02-23
    • 1970-01-01
    相关资源
    最近更新 更多