如何从Guava RangeSet的difference操作中获取闭区间结果?
如何将Guava RangeSet的difference结果转为闭区间?
Guava的RangeSet在处理区间运算时,为了保证区间之间无重叠且无缝衔接,默认会输出半开区间(比如[1..3)或者(6..10])。要把difference操作的结果转成你需要的闭区间形式,我们可以手动遍历结果中的每个区间,根据边界类型调整端点,转换成完全闭合的区间。
实现代码示例
import com.google.common.collect.ImmutableRangeSet; import com.google.common.collect.Range; import java.util.ArrayList; import java.util.List; public class RangeSetExample { public static void main(String[] args) { ImmutableRangeSet<Integer> rangeSet1 = ImmutableRangeSet.of(Range.closed(1, 10)); ImmutableRangeSet<Integer> rangeSet2 = ImmutableRangeSet.of(Range.closed(3, 6)); ImmutableRangeSet<Integer> differenceResult = rangeSet1.difference(rangeSet2); // 将半开区间转换为闭区间集合 List<Range<Integer>> closedRanges = new ArrayList<>(); for (Range<Integer> range : differenceResult.asRanges()) { if (range.hasLowerBound() && range.hasUpperBound()) { Range.BoundType lowerType = range.lowerBoundType(); Range.BoundType upperType = range.upperBoundType(); int lower = range.lowerEndpoint(); int upper = range.upperEndpoint(); if (lowerType == Range.BoundType.CLOSED && upperType == Range.BoundType.OPEN) { // [a..b) → [a..b-1] closedRanges.add(Range.closed(lower, upper - 1)); } else if (lowerType == Range.BoundType.OPEN && upperType == Range.BoundType.CLOSED) { // (a..b] → [a+1..b] closedRanges.add(Range.closed(lower + 1, upper)); } else { // 已经是闭区间或其他类型,直接保留 closedRanges.add(range); } } } // 转换为ImmutableRangeSet(按需使用) ImmutableRangeSet<Integer> closedResult = ImmutableRangeSet.copyOf(closedRanges); System.out.println(closedResult); // 输出:[[1..2], [7..10]] } }
逻辑说明
- 遍历
difference返回的每个区间,通过lowerBoundType()和upperBoundType()判断区间的边界类型 - 针对离散的Integer类型,左闭右开区间
[a..b)等价于包含从a到b-1的所有整数,因此可以直接调整为闭区间[a, b-1] - 左开右闭区间
(a..b]等价于包含从a+1到b的所有整数,调整为闭区间[a+1, b] - 这种转换仅适用于离散数值类型(如Integer、Long),如果是连续类型(如Double),无法通过简单的端点加减实现等价的闭区间转换
内容的提问来源于stack exchange,提问作者Ihor Rybak
相关产品推荐
相关产品推荐

