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は、整数で構成されています。 String、Character、浮動小数点小数などのComparableインターフェイスを実装している限り、任意のタイプの範囲を使用できます。
-
マップに存在しない範囲の値を取得しようとすると、RangeMapはNullを返します
-
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ベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。