Guia de Guava RangeMap

Guia de Guava RangeMap

1. Visão geral

Neste tutorial, mostraremos como usar a interfaceRangeMap do Google Guava e suas implementações.

UmRangeMap é um tipo especial de mapeamento de intervalos não vazios separados para valores não nulos. Usando consultas, podemos procurar o valor para qualquer intervalo específico nesse mapa.

A implementação básica deRangeMap é umTreeRangeMap. Internamente, o mapa usaTreeMap para armazenar a chave como um intervalo e o valor como qualquer objeto Java personalizado.

2. RangeMap do Google Guava

Vamos dar uma olhada em como usar a classeRangeMap.

2.1. Dependência do Maven

Vamos começar adicionando a dependência da biblioteca Guava do Google empom.xml:


    com.google.guava
    guava
    21.0

A versão mais recente da dependência pode ser verificadahere.

3. Criando

Algumas das maneiras pelas quais podemos criar uma instância deRangeMap são:

  • Use o métodocreate da classeTreeRangeMap para criar um mapa mutável:

RangeMap experienceRangeDesignationMap
  = TreeRangeMap.create();
  • Se pretendemos criar um mapa de alcance imutável, use a classeImmutableRangeMap (que segue um padrão builder):

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

4. Usando

Vamos começar com um exemplo simples que mostra o uso deRangeMap.

4.1. Recuperação com base na entrada dentro de um intervalo

Podemos obter um valor associado a um valor dentro de um intervalo de números inteiros:

@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));
}

Nota:

  • O métodoclosed da classeRange assume que o intervalo de valores inteiros está entre 0 e 2 (ambos inclusivos)

  • ORange no exemplo acima consiste em inteiros. Podemos usar um intervalo de qualquer tipo, desde que implemente a interfaceComparable, comoString,Character, decimais de ponto flutuante etc.

  • RangeMap retornaNull quando tentamos obter o valor para um intervalo que não está presente no mapa

  • No caso de umImmutableRangeMap, um intervalo de uma chave não pode se sobrepor a um intervalo de uma chave que precisa ser inserida. Se isso acontecer, obtemos umIllegalArgumentException

  • Tanto as chaves quanto os valores emRangeMap não podem sernull. Se qualquer um deles fornull,, obtemos umNullPointerException

4.2. Removendo um valor com base em umRange

Vamos ver como podemos remover valores. Neste exemplo, mostramos como remover um valor associado a um intervalo inteiro. Também mostramos como remover um valor com base em um intervalo de chaves parcial:

@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));
}

Como pode ser visto, mesmo após remover parcialmente os valores de um intervalo, ainda podemos obter os valores se o intervalo ainda for válido.

4.3. Extensão do alcance da chave

No caso de desejarmos saber qual é a amplitude geral de umRangeMap, podemos usar o métodospan:

@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. Obtendo umSubRangeMap

Quando queremos selecionar uma parte de umRangeMap, podemos usar o métodosubRangeMap:

@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")));
}

Este método retorna a interseção deRangeMap com o parâmetroRange fornecido.

4.5. Obtendo umEntry

Finalmente, se estamos procurando umEntry de umRangeMap, usamos o métodogetEntry:

@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. Conclusão

Neste tutorial, ilustramos exemplos de uso deRangeMap na biblioteca Guava. É predominantemente usado para obter um valor com base na chave especificada como a do mapa.

A implementação desses exemplos pode ser encontrada emthe GitHub project - este é um projeto baseado em Maven, portanto, deve ser fácil de importar e executar como está.