java - Java合并重叠日期间隔
问题描述
通常这种类型的算法是使用 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
解决方案
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);
}
推荐阅读
- c# - Angular UI 应用程序不调用受 AzureAD 保护的 Asp.net 核心 API
- doctrine-orm - 教义继承映射——在更新时添加级联到 id 字段
- sql - 有没有办法将这三个 SQL 查询合并为一个?
- wordpress - 将 codei-gniter 控制器数据调用到 wordpress 并以 json 显示
- python - Numpy linspace 间距不均匀
- javascript - 我怎样才能使目标正确?
- ruby-on-rails - 在 Rails 中延迟作业完成后,有什么方法可以在视图端获取数据作为响应
- jackson - RestAssured - 无法识别的字段,未标记为可忽略
- android - 我的应用程序在启动后崩溃。android studio 上的代码显示没有错误。应用程序安装正确但无法启动
- c# - 文化不变的 StringFormat 不起作用