区间集合 -- RangeSet

2018-01-31 17:13:38   最后更新: 2018-01-31 17:13:38   访问数量:359




上一篇日志中,我们介绍了 guava 的区间结构 -- Range

区间结构 -- Range

 

本文中我们来介绍 Range 的集合 -- RangeSet

顾名思义,RangeSet 是若干个 Range 组成的 Set 结构,guava 提供的 RangeSet 是一个接口,他有以下实现:

  • TreeRangeSet -- 通过红黑树实现的排序 RangeSet
  • ImmutableRangeSet -- 不可变的 RangeSet

 

由于 RangeSet 是利用 jdk1.6 提供的 NavigableMap 特性实现的,因此只有在 jdk1.6 及以上版本才能使用此功能

 

TreeRangeSet、ImmutableRangeSet 都提供了 create 方法,用来创建 RangeSet

 

RangeSet<Long> rangeSet = TreeRangeSet.create(); RangeSet<Long> rangeSet = TreeRangeSet.create(oldRangeSet); // public static <C extends Comparable<?>> TreeRangeSet<C> create(RangeSet<C> rangeSet) RangeSet<Long> rangeSet = TreeRangeSet.create(oldRangeSetIterator); // public static <C extends Comparable<?>> TreeRangeSet<C> create(Iterable<Range<C>> ranges)

 

 

增加区间

  • void add(Range<C> rangeToAdd)

add 方法将一个 Range 对象加入到 RangeSet 中,如果与 RangeSet 中某个 Range 相连,则会合成为一个 Range

 

删除区间

  • void remove(Range<C> rangeToRemove)

在 RangeSet 中删除 rangeToRemove

 

删除 RangeSet

  • void removeAll(RangeSet<C> var1)

在 RangeSet 中删除 RangeSet

 

RangeSet 本质上就是一个 Range 的集合,因此,能够获取一个包含 RangeSet 中所有 Range 的集合通常是非常有用的

 

获取 Range 集合

  • Set<Range<C>> asRanges()

 

 

获取逆序 Range 集合

  • Set<Range<C>> asDescendingSetOfRanges()

这个方法和上面的方法类似,不过它输出的 Range 集合是逆序的

 

  • 示例
RangeSet<Integer> rangeSet = TreeRangeSet.create(); rangeSet.add(Range.closed(1, 4)); rangeSet.add(Range.closed(5, 8)); rangeSet.add(Range.closed(10, 12)); System.out.println(rangeSet.asRanges()); System.out.println(rangeSet.asDescendingSetOfRanges());

 

 

上面的代码输出了:

[[1..4], [5..8], [10..12]]

[[10..12], [5..8], [1..4]]

 

查询包含元素的 Range

  • Range<C> rangeContaining(C value)

rangeContaining 返回了包含元素 value 的 Range

 

扩充集合

  • Range<C> span()

span 运算返回一个 RangeSet 中包含所有区间的最小区间,也就是整个 RangeSet 的最小值与最大值组成的 Range 区间

 

  • 示例
RangeSet<Integer> rangeSet = TreeRangeSet.create(); rangeSet.add(Range.closed(1, 4)); rangeSet.add(Range.closed(5, 8)); rangeSet.add(Range.closed(10, 12)); System.out.println(rangeSet.span());

 

上面的代码输出了 [1..12]

 

补集

  • RangeSet<C> complement()

返回一个集合的补集

 

  • 示例
RangeSet<Integer> rangeSet = TreeRangeSet.create(); rangeSet.add(Range.closed(1, 4)); rangeSet.add(Range.closed(5, 8)); rangeSet.add(Range.closed(10, 12)); System.out.println(rangeSet.complement());

 

上面的代码输出了 [(-∞..1), (4..5), (8..10), (12..+∞)]

 

交集

  • RangeSet<C> subRangeSet(Range<C> view)

subRangeSet 返回了一个 RangeSet 与一个 Range 的交集

但是需要注意的是,TreeRangeSet 具有一个 SubRangeSet 内部类,SubRangeSet 具有一个 Range 成员 restriction,用来限制 SubRangeSet 的范围

一旦执行 subRangeSet 操作后,restriction 将会被设置为传入的参数 Range,此后,返回的 RangeSet 将无法扩充到此范围外

 

  • 示例
RangeSet<Integer> rangeSet = TreeRangeSet.create(); rangeSet.add(Range.closed(1, 4)); rangeSet.add(Range.closed(5, 8)); rangeSet.add(Range.closed(10, 12)); RangeSet<Integer> subRangeSet = rangeSet.subRangeSet(Range.closed(3,6)); System.out.println(subRangeSet);

 

上述代码输出了:[[3..4], [5..6]]

 

接着我们试图执行:

subRangeSet.add(Range.closed(13, 20));

 

抛出了异常:

Exception in thread "main" java.lang.IllegalArgumentException: Cannot add range [13..20] to subRangeSet([3..6]) at com.google.common.base.Preconditions.checkArgument(Preconditions.java:383) at com.google.common.collect.TreeRangeSet$SubRangeSet.add(TreeRangeSet.java:898) at com.techlog.test.testspring.controller.TestController.main(TestController.java:33)

 

 

包含关系

  • boolean encloses(Range<C> range)

返回 RangeSet 是否包含 Range

 

相交关系

  • boolean intersects(Range<C> range)

返回 RangeSet 是否与 Range 相交

 






读书笔记      技术帖      龙潭书斋      range      google      guava      区间      rangeset     


京ICP备15018585号