Guide to Guava RangeSet – Guava RangeSet指南

最后修改: 2017年 1月 23日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’ll show how to use the Google Guava’s RangeSet interface and its implementations.

在本教程中,我们将展示如何使用Google Guava的RangeSet接口及其实现。

A RangeSet is a set comprising of zero or more non-empty, disconnected ranges. When adding a range to a mutable RangeSet, any connected ranges are merged together while empty ranges are ignored.

RangeSet是一个由零个或多个非空的、不相连的范围组成的集合。当添加一个范围到一个可变的RangeSet时,任何连接的范围都被合并在一起,而空的范围被忽略。

The basic implementation of RangeSet is a TreeRangeSet.

RangeSet的基本实现是一个TreeRangeSet

2. Google Guava’s RangeSet

2.Google Guava的RangeSet

Let’s have a look at how to use the RangeSet class.

让我们看一下如何使用RangeSet类。

2.1. Maven Dependency

2.1.Maven的依赖性

Let’s start by adding Google’s Guava library dependency in the pom.xml:

让我们先在pom.xml中加入Google的Guava库依赖。

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.0.1-jre</version>
</dependency>

The latest version of the dependency can be checked here.

最新版本的依赖关系可以在这里查看

3. Creation

3.创造

Let’s explore some of the ways in which we can create an instance of RangeSet.

让我们来探索一些我们可以创建RangeSet实例的方法。

First, we can use the create method from the class TreeRangeSet to create a mutable set:

首先,我们可以使用TreeRangeSet类中的create方法来创建一个可变的集合。

RangeSet<Integer> numberRangeSet = TreeRangeSet.create();

If we already have collections in place, use the create method from the class TreeRangeSet to create a mutable set by passing that collection:

如果我们已经有了集合,使用TreeRangeSet类中的create方法,通过传递该集合创建一个可变的集合。

List<Range<Integer>> numberList = Arrays.asList(Range.closed(0, 2));
RangeSet<Integer> numberRangeSet = TreeRangeSet.create(numberList);

Finally, if we need to create an immutable range set, use the ImmutableRangeSet class (creating which follows a builder pattern):

最后,如果我们需要创建一个不可变的范围集,使用ImmutableRangeSet类(创建时遵循构建器模式)。

RangeSet<Integer> numberRangeSet 
  = new ImmutableRangeSet.<Integer>builder().add(Range.closed(0, 2)).build();

4. Usage

4.使用方法

Let’s start with a simple example that shows the usage of RangeSet.

让我们从一个简单的例子开始,展示RangeSet的用法。

4.1. Adding to a Range

4.1.添加到一个范围

We can check whether the input supplied is within a range present in any of the range items in a set:

我们可以检查所提供的输入是否在一个集合中的任何一个范围项中存在。

@Test
public void givenRangeSet_whenQueryWithinRange_returnsSucessfully() {
    RangeSet<Integer> numberRangeSet = TreeRangeSet.create();

    numberRangeSet.add(Range.closed(0, 2));
    numberRangeSet.add(Range.closed(3, 5));
    numberRangeSet.add(Range.closed(6, 8));

    assertTrue(numberRangeSet.contains(1));
    assertFalse(numberRangeSet.contains(9));
}

Notes:

注意事项。

  • The closed method of the Range class assumes the range of integer values to be between 0 to 2 (both inclusive)
  • The Range in above example consists of integers. We can use a range consisting of any type as long as it implements the Comparable interface such as String, Character, floating point decimals etc
  • In the case of an ImmutableRangeSet, a range item present in the set cannot overlap with a range item that one would like to add. If that happens, we get an IllegalArgumentException
  • Range input to a RangeSet cannot be null. If the input is null, we will get a NullPointerException

4.2. Removing a Range

4.2.删除一个范围

Let’s see how we can remove values from a RangeSet:

让我们看看如何从RangeSet中移除数值。

@Test
public void givenRangeSet_whenRemoveRangeIsCalled_removesSucessfully() {
    RangeSet<Integer> numberRangeSet = TreeRangeSet.create();

    numberRangeSet.add(Range.closed(0, 2));
    numberRangeSet.add(Range.closed(3, 5));
    numberRangeSet.add(Range.closed(6, 8));
    numberRangeSet.add(Range.closed(9, 15));
    numberRangeSet.remove(Range.closed(3, 5));
    numberRangeSet.remove(Range.closed(7, 10));

    assertTrue(numberRangeSet.contains(1));
    assertFalse(numberRangeSet.contains(9));
    assertTrue(numberRangeSet.contains(12));
}

As can be seen, after removal we can still access values present in any of the range items left in the set.

可以看出,在移除之后,我们仍然可以访问集合中剩下的任何一个范围项中存在的值。

4.3. Range Span

4.3 范围跨度

Let’s now see what the overall span of a RangeSet is:

现在让我们看看RangeSet的整体跨度是多少。

@Test
public void givenRangeSet_whenSpanIsCalled_returnsSucessfully() {
    RangeSet<Integer> numberRangeSet = TreeRangeSet.create();

    numberRangeSet.add(Range.closed(0, 2));
    numberRangeSet.add(Range.closed(3, 5));
    numberRangeSet.add(Range.closed(6, 8));
    Range<Integer> experienceSpan = numberRangeSet.span();

    assertEquals(0, experienceSpan.lowerEndpoint().intValue());
    assertEquals(8, experienceSpan.upperEndpoint().intValue());
}

4.4. Getting a Subrange

4.4.获得一个子范围

If we wish to get part of RangeSet based on a given Range, we can use the subRangeSet method:

如果我们希望基于给定的Range获得RangeSet的一部分,我们可以使用subRangeSet方法。

@Test
public void 
  givenRangeSet_whenSubRangeSetIsCalled_returnsSubRangeSucessfully() {
  
    RangeSet<Integer> numberRangeSet = TreeRangeSet.create();

    numberRangeSet.add(Range.closed(0, 2));
    numberRangeSet.add(Range.closed(3, 5));
    numberRangeSet.add(Range.closed(6, 8));
    RangeSet<Integer> numberSubRangeSet 
      = numberRangeSet.subRangeSet(Range.closed(4, 14));

    assertFalse(numberSubRangeSet.contains(3));
    assertFalse(numberSubRangeSet.contains(14));
    assertTrue(numberSubRangeSet.contains(7));
}

4.5. Complement Method

4.5.补强法

Next, let’s get all the values except the one present in RangeSet, using the complement method:

接下来,让我们使用RangeSet方法,获得所有的值,除了存在于RangeSet中的值。

@Test
public void givenRangeSet_whenComplementIsCalled_returnsSucessfully() {
    RangeSet<Integer> numberRangeSet = TreeRangeSet.create();

    numberRangeSet.add(Range.closed(0, 2));
    numberRangeSet.add(Range.closed(3, 5));
    numberRangeSet.add(Range.closed(6, 8));
    RangeSet<Integer> numberRangeComplementSet
      = numberRangeSet.complement();

    assertTrue(numberRangeComplementSet.contains(-1000));
    assertFalse(numberRangeComplementSet.contains(2));
    assertFalse(numberRangeComplementSet.contains(3));
    assertTrue(numberRangeComplementSet.contains(1000));
}

4.6. Intersection With a Range

4.6.与一个范围的交集

Finally, when we would like to check whether a range interval present in RangeSet intersects with some or all the values in another given range, we can make use of the intersect method:

最后,当我们想检查RangeSet中的一个区间是否与另一个给定区间的一些或所有的值相交时,我们可以使用intersect方法。

@Test
public void givenRangeSet_whenIntersectsWithinRange_returnsSucessfully() {
    RangeSet<Integer> numberRangeSet = TreeRangeSet.create();

    numberRangeSet.add(Range.closed(0, 2));
    numberRangeSet.add(Range.closed(3, 10));
    numberRangeSet.add(Range.closed(15, 18));

    assertTrue(numberRangeSet.intersects(Range.closed(4, 17)));
    assertFalse(numberRangeSet.intersects(Range.closed(19, 200)));
}

5. Conclusion

5.结论

In this tutorial, we illustrated the RangeSet of the Guava library using some examples. The RangeSet is predominantly used to check whether a value falls within a certain range present in the set.

在本教程中,我们用一些例子说明了Guava库的RangeSetRangeSet主要用于检查一个值是否属于集合中的某个范围。

The implementation of these examples can be found in the GitHub project – this is a Maven-based project, so it should be easy to import and run as is.

这些例子的实现可以在GitHub项目中找到–这是一个基于Maven的项目,所以应该很容易导入并按原样运行。