Guida a Guava RangeMap

1. Panoramica

In questo tutorial, mostreremo come utilizzare l' interfaccia RangeMap di Google Guava e le sue implementazioni.

Una RangeMap è un tipo speciale di mappatura da intervalli non vuoti disgiunti a valori non nulli. Utilizzando le query, possiamo cercare il valore per qualsiasi intervallo particolare in quella mappa.

L'implementazione di base di RangeMap è una TreeRangeMap . Internamente la mappa fa uso di una TreeMap per memorizzare la chiave come un intervallo e il valore come qualsiasi oggetto Java personalizzato.

2. RangeMap di Google Guava

Diamo un'occhiata a come utilizzare la classe RangeMap .

2.1. Dipendenza da Maven

Iniziamo aggiungendo la dipendenza della libreria Guava di Google nel pom.xml :

 com.google.guava guava 29.0-jre 

L'ultima versione della dipendenza può essere verificata qui.

3. Creazione

Alcuni dei modi in cui possiamo creare un'istanza di RangeMap sono:

  • Usa il metodo create dalla classe TreeRangeMap per creare una mappa mutabile:
RangeMap experienceRangeDesignationMap = TreeRangeMap.create();
  • Se intendiamo creare una mappa di intervallo immutabile, usa la classe ImmutableRangeMap (che segue un modello builder):
RangeMap experienceRangeDesignationMap = new ImmutableRangeMap.builder() .put(Range.closed(0, 2), "Associate") .build(); 

4. Utilizzando

Cominciamo con un semplice esempio che mostra l'utilizzo di RangeMap .

4.1. Recupero basato sull'input entro un intervallo

Possiamo ottenere un valore associato a un valore all'interno di un intervallo di numeri interi:

@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:

  • Il metodo closed della classe Range presuppone che l'intervallo di valori interi sia compreso tra 0 e 2 (entrambi inclusi)
  • L' intervallo nell'esempio precedente è costituito da numeri interi. Possiamo utilizzare un intervallo di qualsiasi tipo, purché implementi l' interfaccia Comparable come String , Character , decimali a virgola mobile ecc.
  • RangeMap restituisce Null quando proviamo a ottenere il valore per un intervallo che non è presente in map
  • In un caso di ImmutableRangeMap , un intervallo di una chiave non può sovrapporsi a un intervallo di una chiave che deve essere inserita. Se ciò accade, otteniamo un'eccezione IllegalArgumentException
  • Sia le chiavi che i valori in RangeMap non possono essere nulli . Se uno di loro è null, otteniamo una NullPointerException

4.2. Rimozione di un valore in base a un intervallo

Vediamo come possiamo rimuovere i valori. In questo esempio, mostriamo come rimuovere un valore associato a un intero intervallo. Mostriamo anche come rimuovere un valore basato su un intervallo di chiavi parziale:

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

Come si può vedere, anche dopo aver rimosso parzialmente i valori da un intervallo, possiamo comunque ottenere i valori se l'intervallo è ancora valido.

4.3. Portata dell'intervallo chiave

Nel caso in cui desideriamo sapere qual è l' estensione complessiva di una RangeMap , possiamo utilizzare il metodo 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. Ottenere una SubRangeMap

Quando vogliamo selezionare una parte da una RangeMap , possiamo usare il metodo 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"))); }

Questo metodo restituisce l'intersezione di RangeMap con il parametro Range specificato.

4.5. Ottenere una voce

Infine, se stiamo cercando una voce da una RangeMap , utilizziamo il metodo 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
    
      experienceEntry = experienceRangeDesignationMap.getEntry(10); assertEquals(Range.closed(9, 15), experienceEntry.getKey()); assertEquals("Executive Director", experienceEntry.getValue()); }
    

5. conclusione

In questo tutorial, abbiamo illustrato esempi di utilizzo di RangeMap nella libreria Guava. Viene utilizzato principalmente per ottenere un valore basato sulla chiave specificata come a dalla mappa.

L'implementazione di questi esempi può essere trovata nel progetto GitHub: questo è un progetto basato su Maven, quindi dovrebbe essere facile da importare ed eseguire così com'è.