Руководство по Guava RangeMap

Руководство по Guava RangeMap

1. обзор

В этом руководстве мы покажем, как использовать интерфейсRangeMap Google Guava и его реализации.

RangeMap - это особый вид отображения непересекающихся непустых диапазонов в ненулевые значения. Используя запросы, мы можем посмотреть значение для любого конкретного диапазона на этой карте.

Базовая реализацияRangeMap - этоTreeRangeMap. Внутренне карта используетTreeMap для хранения ключа как диапазона и значения как любого настраиваемого объекта Java.

2. RangeMap в Google Guava

Давайте посмотрим, как использовать классRangeMap.

2.1. Maven Dependency

Начнем с добавления зависимости библиотеки Google Guava вpom.xml:


    com.google.guava
    guava
    21.0

Последнюю версию зависимости можно проверитьhere.

3. Создание

Вот некоторые из способов, которыми мы можем создать экземплярRangeMap:

  • Используйте методcreate из классаTreeRangeMap, чтобы создать изменяемую карту:

RangeMap experienceRangeDesignationMap
  = TreeRangeMap.create();
  • Если мы намерены создать неизменяемую карту диапазонов, используйте классImmutableRangeMap (который следует шаблону построителя):

RangeMap experienceRangeDesignationMap
  = new ImmutableRangeMap.builder()
  .put(Range.closed(0, 2), "Associate")
  .build();

4. С помощью

Начнем с простого примера, показывающего использованиеRangeMap.

4.1. Получение на основе ввода в пределах диапазона

Мы можем получить значение, связанное со значением в диапазоне целых чисел:

@Test
public void givenRangeMap_whenQueryWithinRange_returnsSucessfully() {
    RangeMap 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));
}

Замечания:

  • Методclosed классаRange предполагает, что диапазон целочисленных значений находится в диапазоне от 0 до 2 (оба включительно)

  • Range в приведенном выше примере состоит из целых чисел. Мы можем использовать диапазон любого типа, если он реализует интерфейсComparable, такой какString,Character, десятичные числа с плавающей запятой и т. Д.

  • RangeMap возвращаетNull, когда мы пытаемся получить значение для диапазона, которого нет на карте

  • В случаеImmutableRangeMap диапазон одного ключа не может перекрываться с диапазоном ключа, который необходимо вставить. Если это произойдет, мы получимIllegalArgumentException

  • И ключи, и значения вRangeMap не могут бытьnull. Если один из нихnull,, мы получаемNullPointerException

4.2. Удаление значения на основеRange

Давайте посмотрим, как мы можем удалить значения. В этом примере мы покажем, как удалить значение, связанное со всем диапазоном. Мы также покажем, как удалить значение, основанное на частичном диапазоне ключей:

@Test
public void givenRangeMap_whenRemoveRangeIsCalled_removesSucessfully() {
    RangeMap 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));
}

Как видно, даже после частичного удаления значений из диапазона, мы все равно можем получить значения, если диапазон все еще действителен.

4.3. Диапазон ключевого диапазона

В случае, если мы хотели бы знать, каков общий диапазонRangeMap, мы можем использовать методspan:

@Test
public void givenRangeMap_whenSpanIsCalled_returnsSucessfully() {
    RangeMap 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 experienceSpan = experienceRangeDesignationMap.span();

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

4.4. ПолучениеSubRangeMap

Когда мы хотим выбрать часть изRangeMap, мы можем использовать методsubRangeMap:

@Test
public void givenRangeMap_whenSubRangeMapIsCalled_returnsSubRangeSuccessfully() {
    RangeMap 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 experiencedSubRangeDesignationMap
      = experienceRangeDesignationMap.subRangeMap(Range.closed(4, 14));

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

Этот метод возвращает пересечениеRangeMap с заданным параметромRange.

4.5. ПолучениеEntry

Наконец, если мы ищемEntry изRangeMap, мы используем методgetEntry:

@Test
public void givenRangeMap_whenGetEntryIsCalled_returnsEntrySucessfully() {
    RangeMap 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, String> experienceEntry
      = experienceRangeDesignationMap.getEntry(10);

    assertEquals(Range.closed(9, 15), experienceEntry.getKey());
    assertEquals("Executive Director", experienceEntry.getValue());
}

5. Заключение

В этом руководстве мы проиллюстрировали примеры использованияRangeMap в библиотеке Guava. Он преимущественно используется для получения значения, основанного на ключе, указанном на карте.

Реализацию этих примеров можно найти вthe GitHub project - это проект на основе Maven, поэтому его будет легко импортировать и запускать как есть.