グアバRangeMapへのガイド

Guava RangeMapのガイド

1. 概要

このチュートリアルでは、Google GuavaのRangeMapインターフェースとその実装の使用方法を示します。

RangeMapは、互いに素な空でない範囲からnull以外の値への特別な種類のマッピングです。 クエリを使用して、そのマップの特定の範囲の値を検索できます。

RangeMapの基本的な実装はTreeRangeMapです。 内部的には、マップはTreeMapを使用して、キーを範囲として格納し、値をカスタムJavaオブジェクトとして格納します。

2. Google GuavaのRangeMap

RangeMapクラスの使用方法を見てみましょう。

2.1. メーベン依存

pom.xmlにGoogleのGuavaライブラリの依存関係を追加することから始めましょう。


    com.google.guava
    guava
    21.0

依存関係の最新バージョンはhereで確認できます。

3. 作成

RangeMapのインスタンスを作成する方法のいくつかは次のとおりです。

  • TreeRangeMapクラスのcreateメソッドを使用して、変更可能なマップを作成します。

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

注意:

  • Rangeクラスのclosedメソッドは、整数値の範囲が0から2(両方を含む)であると想定しています。

  • 上記の例のRangeは、整数で構成されています。 StringCharacter、浮動小数点小数などのComparableインターフェイスを実装している限り、任意のタイプの範囲を使用できます。

  • マップに存在しない範囲の値を取得しようとすると、RangeMapNullを返します

  • ImmutableRangeMapの場合、1つのキーの範囲を、挿入する必要のあるキーの範囲とオーバーラップさせることはできません。 その場合、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を取得する

最後に、RangeMapからEntryを探している場合は、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. 結論

このチュートリアルでは、GuavaライブラリでRangeMapを使用する例を示しました。 主にマップから指定されたキーに基づいて値を取得するために使用されます。

これらの例の実装はthe GitHub projectにあります。これはMavenベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。