有效地找到 BitSet 中连续未设置位的范围
Efficiently find ranges of consecutive non-set bits in BitSet
我正在尝试使用 BitSet 表示特定日期的日历 available/unavailable 时段,每个位代表 15 分钟。设置的位代表被阻止的日历事件。为了获得空闲的插槽,我需要找到未设置位的范围。
我有以下 BitSet
00000000000000000011111001000000000011100000000000000000011000
如何有效地找到未设置的位的范围。在这种情况下
(1,18) 和 (24,25) 和 (27,36) 等
下面是我目前写的代码,感觉效率不高,也不干净。
int startIndex = -1;
int nextIndex = -1;
for(int i = getSlotIndex(currentWorkingStartDate); i <= getSlotIndex(currentWorkingEndDate); i++) {
if(!matrix.get(i)) {
if(startIndex == -1) {
startIndex = i;
nextIndex = i;
}else {
nextIndex = i;
}
}else if(startIndex != -1){
ZonedDateTime availableStartDate = day.plusHours((startIndex/4)).plusMinutes(startIndex%4 * 15);
ZonedDateTime availableEndDate = availableStartDate.plusMinutes((nextIndex - startIndex + 1) * 15L);
currAvailabilitySlots.addAll(
getSlotsBasedOnDurationWithTimeZone(new SlotModel(availableStartDate,availableEndDate),durationOfSlot,candidateTimeZoneId));
startIndex = -1;
nextIndex = -1;
}
}
if(startIndex != -1) {
ZonedDateTime availableStartDate = day.plusHours((startIndex/4)).plusMinutes(startIndex%4 * 15);
ZonedDateTime availableEndDate = availableStartDate.plusMinutes((nextIndex - startIndex) * 15L);
currAvailabilitySlots.addAll(
getSlotsBasedOnDurationWithTimeZone(new SlotModel(availableStartDate,availableEndDate),durationOfSlot,candidateTimeZoneId));
}
有一种方法可以获取给定索引处或之后的下一个未设置位:BitSet.nextClearBit(int)
。
有一个补充方法,nextSetBit(int)
,用于查找下一个设置位。
所以,你可以用前者找到范围的开始,用后者找到范围的结束。
您需要小心处理方法的 return 值:
- 如果
nextSetBit
returns -1,这意味着当前运行个清除位扩展到BitSet的末尾。
nextClearBit
不会 return -1,因为 BitSet 没有 clearly-defined 的大小清除位 - 它们本质上无限扩展,但实际上只分配存储空间来保存设置位。因此,如果 nextClearBit
returns 的值超出 BitSet 的 逻辑 大小(即超出 day/date范围),你知道你可以停止搜索。
我正在尝试使用 BitSet 表示特定日期的日历 available/unavailable 时段,每个位代表 15 分钟。设置的位代表被阻止的日历事件。为了获得空闲的插槽,我需要找到未设置位的范围。
我有以下 BitSet
00000000000000000011111001000000000011100000000000000000011000
如何有效地找到未设置的位的范围。在这种情况下 (1,18) 和 (24,25) 和 (27,36) 等
下面是我目前写的代码,感觉效率不高,也不干净。
int startIndex = -1;
int nextIndex = -1;
for(int i = getSlotIndex(currentWorkingStartDate); i <= getSlotIndex(currentWorkingEndDate); i++) {
if(!matrix.get(i)) {
if(startIndex == -1) {
startIndex = i;
nextIndex = i;
}else {
nextIndex = i;
}
}else if(startIndex != -1){
ZonedDateTime availableStartDate = day.plusHours((startIndex/4)).plusMinutes(startIndex%4 * 15);
ZonedDateTime availableEndDate = availableStartDate.plusMinutes((nextIndex - startIndex + 1) * 15L);
currAvailabilitySlots.addAll(
getSlotsBasedOnDurationWithTimeZone(new SlotModel(availableStartDate,availableEndDate),durationOfSlot,candidateTimeZoneId));
startIndex = -1;
nextIndex = -1;
}
}
if(startIndex != -1) {
ZonedDateTime availableStartDate = day.plusHours((startIndex/4)).plusMinutes(startIndex%4 * 15);
ZonedDateTime availableEndDate = availableStartDate.plusMinutes((nextIndex - startIndex) * 15L);
currAvailabilitySlots.addAll(
getSlotsBasedOnDurationWithTimeZone(new SlotModel(availableStartDate,availableEndDate),durationOfSlot,candidateTimeZoneId));
}
有一种方法可以获取给定索引处或之后的下一个未设置位:BitSet.nextClearBit(int)
。
有一个补充方法,nextSetBit(int)
,用于查找下一个设置位。
所以,你可以用前者找到范围的开始,用后者找到范围的结束。
您需要小心处理方法的 return 值:
- 如果
nextSetBit
returns -1,这意味着当前运行个清除位扩展到BitSet的末尾。 nextClearBit
不会 return -1,因为 BitSet 没有 clearly-defined 的大小清除位 - 它们本质上无限扩展,但实际上只分配存储空间来保存设置位。因此,如果nextClearBit
returns 的值超出 BitSet 的 逻辑 大小(即超出 day/date范围),你知道你可以停止搜索。