Guide to Guava RangeMap – 番石榴范围地图指南

最后修改: 2017年 1月 24日

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

1. Overview

1.概述

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

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

A RangeMap is a special kind of mapping from disjoint non-empty ranges to non-null values. Using queries, we may look up the value for any particular range in that map.

RangeMap是一种特殊的映射,从不相连的非空范围到非空值。使用查询,我们可以查找该映射中任何特定范围的值。

The basic implementation of RangeMap is a TreeRangeMap. Internally the map makes use of a TreeMap to store the key as a range and the value as any custom Java object.

RangeMap的基本实现是一个TreeRangeMap。在内部,该地图利用TreeMap来存储作为范围的键和作为任何自定义Java对象的值。

2. Google Guava’s RangeMap

2.Google Guava的RangeMap

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

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

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. Creating

3.创造

Some of the ways in which we may create an instance of RangeMap are:

我们可以创建RangeMap的实例的一些方法是。

  • Use the create method from the TreeRangeMap class to create a mutable map:
RangeMap<Integer, String> experienceRangeDesignationMap
  = TreeRangeMap.create();
  • If we intend to create an immutable range map, use the ImmutableRangeMap class (which follows a builder pattern):
RangeMap<Integer, String> experienceRangeDesignationMap
  = new ImmutableRangeMap.<Integer, String>builder()
  .put(Range.closed(0, 2), "Associate")
  .build();

4. Using

4.使用

Let’s start with a simple example showing the usage of RangeMap.

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

4.1. Retrieval Based on Input Within a Range

4.1.基于某一范围内的输入的检索

We can get a value associated with a value within a range of integers:

我们可以在一个整数的范围内得到一个与之相关的值。

@Test
public void givenRangeMap_whenQueryWithinRange_returnsSucessfully() {
    RangeMap<Integer, String> experienceRangeDesignationMap 
     = TreeRangeMap.create();

    experienceRangeDesignationMap.put(
      Range.closed(0, 2), "Associate");
    experienceRangeDesignationMap.put(
      Range.closed(3, 5), "Senior Associate");
    experienceRangeDesignationMap.put(
      Range.closed(6, 8),  "Vice President");
    experienceRangeDesignationMap.put(
      Range.closed(9, 15), "Executive Director");

    assertEquals("Vice President", 
      experienceRangeDesignationMap.get(6));
    assertEquals("Executive Director", 
      experienceRangeDesignationMap.get(15));
}

Note:

请注意。

  • The closed method of the Range class assumes the range of integer values to be between 0 to 2 (both inclusive)
  • The Range in the above example consists of integers. We may use a range of any type, as long as it implements the Comparable interface such as String, Character, floating point decimals etc.
  • RangeMap returns Null when we try to get the value for a range that is not present in map
  • In a case of an ImmutableRangeMap, a range of one key cannot overlap with a range of a key that needs to be inserted. If that happens, we get an IllegalArgumentException
  • Both keys and values in the RangeMap cannot be null. If either one of them is null, we get a NullPointerException

4.2. Removing a Value Based on a Range

4.2.根据范围删除一个值

Let’s see how we can remove values. In this example, we show how to remove a value associated with an entire range. We also show how to remove a value based on a partial key range:

让我们看看我们如何删除数值。在这个例子中,我们展示了如何删除一个与整个范围相关的值。我们还展示了如何删除一个基于部分键范围的值。

@Test
public void givenRangeMap_whenRemoveRangeIsCalled_removesSucessfully() {
    RangeMap<Integer, String> experienceRangeDesignationMap 
      = TreeRangeMap.create();

    experienceRangeDesignationMap.put(
      Range.closed(0, 2), "Associate");
    experienceRangeDesignationMap.put(
      Range.closed(3, 5), "Senior Associate");
    experienceRangeDesignationMap.put(
      Range.closed(6, 8), "Vice President");
    experienceRangeDesignationMap.put(
      Range.closed(9, 15), "Executive Director");
 
    experienceRangeDesignationMap.remove(Range.closed(9, 15));
    experienceRangeDesignationMap.remove(Range.closed(1, 4));
  
    assertNull(experienceRangeDesignationMap.get(9));
    assertEquals("Associate", 
      experienceRangeDesignationMap.get(0));
    assertEquals("Senior Associate", 
      experienceRangeDesignationMap.get(5));
    assertNull(experienceRangeDesignationMap.get(1));
}

As can be seen, even after partially removing values from a range, we still can get the values if the range is still valid.

可以看出,即使从一个范围中删除了部分数值,如果这个范围仍然有效,我们仍然可以得到这些数值。

4.3. Span of Key Range

4.3.关键范围的跨度

In case we would like to know what the overall span of a RangeMap is, we may use the span method:

如果我们想知道一个RangeMap的总体跨度是多少,我们可以使用span方法。

@Test
public void givenRangeMap_whenSpanIsCalled_returnsSucessfully() {
    RangeMap<Integer, String> experienceRangeDesignationMap = TreeRangeMap.create();
    experienceRangeDesignationMap.put(Range.closed(0, 2), "Associate");
    experienceRangeDesignationMap.put(Range.closed(3, 5), "Senior Associate");
    experienceRangeDesignationMap.put(Range.closed(6, 8), "Vice President");
    experienceRangeDesignationMap.put(Range.closed(9, 15), "Executive Director");
    experienceRangeDesignationMap.put(Range.closed(16, 30), "Managing Director");
    Range<Integer> experienceSpan = experienceRangeDesignationMap.span();

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

4.4. Getting a SubRangeMap

4.4.获得一个SubRangeMap

When we want to select a part from a RangeMap, we may use the subRangeMap method:

当我们想从一个RangeMap中选择一个部分时,我们可以使用subRangeMap方法。

@Test
public void givenRangeMap_whenSubRangeMapIsCalled_returnsSubRangeSuccessfully() {
    RangeMap<Integer, String> experienceRangeDesignationMap = TreeRangeMap.create();

    experienceRangeDesignationMap
      .put(Range.closed(0, 2), "Associate");
    experienceRangeDesignationMap
      .put(Range.closed(3, 5), "Senior Associate");
    experienceRangeDesignationMap
      .put(Range.closed(6, 8), "Vice President");
    experienceRangeDesignationMap
      .put(Range.closed(8, 15), "Executive Director");
    experienceRangeDesignationMap
      .put(Range.closed(16, 30), "Managing Director");
    RangeMap<Integer, String> experiencedSubRangeDesignationMap
      = experienceRangeDesignationMap.subRangeMap(Range.closed(4, 14));

    assertNull(experiencedSubRangeDesignationMap.get(3));
    assertTrue(experiencedSubRangeDesignationMap.asMapOfRanges().values()
      .containsAll(Arrays.asList("Executive Director", "Vice President", "Executive Director")));
}

This method returns the intersection of the RangeMap with the given Range parameter.

该方法返回RangeMap与给定Range参数的交点。

4.5. Getting an Entry

4.5.获得一个条目

Finally, if we are looking for an Entry from a RangeMap, we use the getEntry method:

最后,如果我们要从RangeMap中寻找一个Entry,我们使用getEntry方法。

@Test
public void givenRangeMap_whenGetEntryIsCalled_returnsEntrySucessfully() {
    RangeMap<Integer, String> experienceRangeDesignationMap 
      = TreeRangeMap.create();

    experienceRangeDesignationMap.put(
      Range.closed(0, 2), "Associate");
    experienceRangeDesignationMap.put(
      Range.closed(3, 5), "Senior Associate");
    experienceRangeDesignationMap.put(
      Range.closed(6, 8), "Vice President");
    experienceRangeDesignationMap.put(
      Range.closed(9, 15), "Executive Director");
    Map.Entry<Range<Integer>, String> experienceEntry 
      = experienceRangeDesignationMap.getEntry(10);
       
    assertEquals(Range.closed(9, 15), experienceEntry.getKey());
    assertEquals("Executive Director", experienceEntry.getValue());
}

5. Conclusion

5.结论

In this tutorial, we illustrated examples of using the RangeMap in the Guava library. It is predominantly used to get a value based on the key specified as a from the map.

在本教程中,我们说明了Guava库中使用RangeMap的例子。它主要是用来根据指定的键从地图中获得一个值。

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的项目,所以应该很容易导入并按现状运行。