Guava RangeSet 类
一、类声明
@Beta @GwtIncompatible public interface RangeSet<C extends Comparable>
实现类:ImmutableRangeSet
, TreeRangeSet
二、接口方法
官方文档:https://google.github.io/guava/releases/27.0.1-jre/api/docs/com/google/common/collect/RangeSet.html
修饰符和类型 | 方法描述 |
---|---|
void | add(Range<C> range) 将指定范围添加到此RangeSet. |
default void | addAll(Iterable<Range<C>> ranges) 将所有指定范围添加到此范围集 |
void | addAll(RangeSet<C> other) 将指定范围集中的所有范围添加到此范围集. |
Set<Range<C>> | asDescendingSetOfRanges() 返回组成此范围集的断开连接的范围的降序视图. |
Set<Range<C>> | asRanges() 用Set<Range |
void | clear() Removes all ranges from this RangeSet (optional operation). |
RangeSet<C> | complement() 返回RangeSet的补集视图。complement也是RangeSet类型,包含了不相连的、非空的区间。 |
boolean | contains(C value) RangeSet最基本的操作,判断RangeSet中是否有任何区间包含给定元素。 |
boolean | encloses(Range<C> otherRange) 简单明了,判断RangeSet中是否有任何区间包括给定区间。 |
default boolean | enclosesAll(Iterable<Range<C>> other) 如果对于其他成员范围,则返回true,在此范围集中存在包含它的成员范围. |
boolean | enclosesAll(RangeSet<C> other) 如果对于其他成员范围,则返回true,在此范围集中存在包含它的成员范围. |
boolean | equals(@Nullable Object obj) 如果obj是根据Range.equals(Object)包含相同范围的另一个RangeSet,则返回true。 |
int | hashCode() 返回 asRanges().hashCode(). |
boolean | intersects(Range<C> otherRange) 如果此范围集中的成员范围和指定范围都包含非空范围,则返回true. |
boolean | isEmpty() 如果此范围集不包含范围,则返回true。 |
Range<C> | rangeContaining(C value) 返回包含给定元素的区间;若没有这样的区间,则返回null。 |
void | remove(Range<C> range) 从此RangeSet中删除指定的范围. |
default void | removeAll(Iterable<Range<C>> ranges) 从此范围集中删除所有指定范围. |
void | removeAll(RangeSet<C> other) 从此范围集中删除指定范围集中的所有范围. |
Range<C> | span() 返回包括RangeSet中所有区间的最小区间。 |
RangeSet<C> | subRangeSet(Range<C> view) 返回RangeSet与给定Range的交集视图。这扩展了传统排序集合中的headSet、subSet和tailSet操作。 |
String | toString() 返回此范围集的可读字符串表示形式。 |
三、使用
RangeSet
类是一个接口,需要用它的子类来声明一个 RangeSet 型的对象,实现 RangeSet 接口的类有 ImmutableRangeSet
和 TreeRangeSet
,ImmutableRangeSet 是一个不可修改的 RangeSet,而 TreeRangeSet 是利用树的形式来实现。下面主要谈 TreeRangeSet 的用法:
public void testRangeSet(){ RangeSet rangeSet = TreeRangeSet.create(); rangeSet.add(Range.closed(1, 10)); System.out.println(rangeSet); // [[1..10]] rangeSet.add(Range.closedOpen(11, 15)); System.out.println(rangeSet); // [[1..10], [11..15)] rangeSet.add(Range.open(15, 20)); System.out.println(rangeSet); // [[1..10], [11..15), (15..20)] rangeSet.add(Range.openClosed(0, 0)); System.out.println(rangeSet); // [[1..10], [11..15), (15..20)] rangeSet.remove(Range.open(5, 10)); System.out.println(rangeSet); // [[1..5], [10..10], [11..15), (15..20)] }
上面函数的运行结果如下所示:
[[1..10]] [[1..10], [11..15)] [[1..10], [11..15), (15..20)] [[1..10], [11..15), (15..20)] [[1..5], [10..10], [11..15), (15..20)]
对 Range
类的方法不熟悉,请阅读之前文章
(1)遍历
那如果我们需要遍历rangeSet中的所有元素可以用下面方法实现
// 方法1 // rangeSet.asDescendingSetOfRanges().forEach(System.out::println); // 倒序 Iterator<Range> iterator = rangeSet.asRanges().iterator(); while(iterator.hasNext()){ Range next = iterator.next(); System.out.println(next); } // 方法2 rangeSet.asRanges().forEach(System.out::println);
运行结果:
[1..5] [10..10] [11..15) (15..20)
(2)互补范围
如果我们需要得到 rangeSet
互补的范围,我们可以用 RangeSet
提供的 complement()
方法,rangeSet.complement()
同样是一个 RangeSet
,其中的元素也是互不相交、且不为空的 RangeSet
,那么 rangeSet
的互补集可以像下面这样来写:
RangeSet complement = rangeSet.complement(); System.out.println(complement);
得到的结果是:
[(-∞..1), (5..10), (10..11), [15..15], [20..+∞)]
正好是rangeSet的互补。
(3)包含
如果需要在 rangeSet 中查询某个元素是否在rangeSet中,可以用 contains(C)
来实现,其中 C extends java.lang.Comparable
。
比如我想得到上述rangeSet是否包含15,可以这样写:
boolean isIn = rangeSet.contains(15); System.out.println(isIn); // false,因为上述范围不包含元素15.
(4)查找范围
如果想知道某个元素是在rangeSet中哪个范围里面,可以这样写:
Range integerRange = rangeSet.rangeContaining(17); System.out.println(integerRange); // 输出 `(15..20)`,因为17被包含在 `(15..20)`中 ,所以输出这个范围。
如果想知道某个范围是否包含在rangeSet的范围中,可以这样写:
boolean encloses = rangeSet.encloses(Range.closedOpen(18, 20)); System.out.println(encloses); // true.因为范围(18,20)包含在范围(15,20)中 encloses = rangeSet.encloses(Range.closedOpen(5, 20)); System.out.println(encloses); // false 因为范围(5,20)不被rangeSet中任何范围包含.
RangeSet描述了一组不相连的、非空的区间。当把一个区间添加到可变的RangeSet时,所有相连的区间会被合并,空区间会被忽略。例如:
RangeSet<Integer> rangeSet = TreeRangeSet.create(); rangeSet.add(Range.closed(1, 10)); // {[1,10]} rangeSet.add(Range.closedOpen(11, 15)); // 不相连区间:{[1,10], [11,15)} rangeSet.add(Range.closedOpen(15, 20)); // 相连区间; {[1,10], [11,20)} rangeSet.add(Range.openClosed(0, 0)); // 空区间; {[1,10], [11,20)} rangeSet.remove(Range.open(5, 10)); // 分割[1, 10]; {[1,5], [10,10], [11,20)}
请注意,要合并 Range.closed(1, 10)
和 Range.closedOpen(11, 15)
这样的区间,你需要首先用 Range.canonical(DiscreteDomain)
对区间进行预处理,例如 DiscreteDomain.integers()
。
注:RangeSet不支持GWT,也不支持JDK5和更早版本;因为,RangeSet需要充分利用JDK6中NavigableMap的特性。
四、相关文章
未经允许请勿转载:程序喵 » Google Guava 快速入门 —— 【新集合】RangeSet 类