Usually this type of algorithm is done using SQL (gaps and islands) but I need to find a way to do it in Java.
I have a Set of objects : Set<UnavailableBlock>
The UnavailableBlock
class is as follows (simplified):
@Getter
@Setter
@AllArgsConstructor
@ToString
public class UnavailableBlock{
OffsetDateTime blockStartTime;
OffsetDateTime blockEndTime;
}
Overlapping intervals is allowed, so I'm trying to return a Set<UnavailableBlock>
but with merged intervals leaving the respective gaps in between. I'm using OffsetDateTime and need to take in account the time.
For example (using 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);
}
The problem is that I keep getting blocks that overlap:
Orange = Before merge
Green = After merge
NB: I'm using Spring Boot with lombok annotations