グアバレンジセットガイド

1概要

このチュートリアルでは、Google Guavaの RangeSet インターフェイスとその実装の使い方を説明します。

RangeSet は、0個以上の空でない切断された範囲で構成される集合です。可変の RangeSet に範囲を追加すると、空の範囲は無視されますが、接続されている範囲はすべてマージされます。

RangeSet の基本的な実装は TreeRangeSet です。

2 Google Guavaの RangeSet

RangeSet クラスの使い方を見てみましょう。

2.1. Mavenの依存関係

まず、 pom.xml にGoogleのGuavaライブラリ依存関係を追加します。

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>21.0</version>
</dependency>

依存関係の最新バージョンはhttps://search.maven.org/classic/#search%7C1%7Cg%3A%22com.google.guava%22%20AND%20a%3A%22guava%22[]で確認できます。ここに]。

3作成

RangeSet のインスタンスを作成する方法をいくつか探りましょう。

まず、クラス TreeRangeSet create メソッドを使用して可変セットを作成します。

RangeSet<Integer> numberRangeSet = TreeRangeSet.create();

コレクションがすでに用意されている場合は、クラス TreeRangeSet create メソッドを使用して、そのコレクションを渡して可変セットを作成します。

List<Range<Integer>> numberList = Arrays.asList(Range.closed(0, 2));
RangeSet<Integer> numberRangeSet = TreeRangeSet.create(numberList);

最後に、不変の範囲セットを作成する必要がある場合は、 ImmutableRangeSet クラスを使用します(作成パターンはビルダーパターンに従います)。

RangeSet<Integer> numberRangeSet
  = new ImmutableRangeSet.<Integer>builder().add(Range.closed(0, 2)).build();

4使用法

RangeSet の使い方を示す簡単な例から始めましょう。

4.1. 範囲に追加する

提供された入力が、セット内のいずれかの範囲項目に存在する範囲内にあるかどうかを確認できます。

@Test
public void givenRangeSet__whenQueryWithinRange__returnsSucessfully() {
    RangeSet<Integer> numberRangeSet = TreeRangeSet.create();

    numberRangeSet.add(Range.closed(0, 2));
    numberRangeSet.add(Range.closed(3, 5));
    numberRangeSet.add(Range.closed(6, 8));

    assertTrue(numberRangeSet.contains(1));
    assertFalse(numberRangeSet.contains(9));
}

ノート:

  • Range クラスの closed メソッドは整数の範囲を想定しています

0から2までの値(両端を含む) ** 上記の例の Range は整数で構成されています。範囲を使用できます

Comparable を実装している限り、任意の型からなる String Character 、浮動小数点数などのインタフェース ** ImmutableRangeSet の場合、セット内に存在する範囲項目

追加したい範囲項目と重複することはできません。もしそうなら 起こる、我々は IllegalArgumentException を得る ** RangeSet への範囲入力はnullにできません。入力が null の場合、

NullPointerException が発生します

4.2. 範囲を削除する

RangeSet から値を削除する方法を見てみましょう。

@Test
public void givenRangeSet__whenRemoveRangeIsCalled__removesSucessfully() {
    RangeSet<Integer> numberRangeSet = TreeRangeSet.create();

    numberRangeSet.add(Range.closed(0, 2));
    numberRangeSet.add(Range.closed(3, 5));
    numberRangeSet.add(Range.closed(6, 8));
    numberRangeSet.add(Range.closed(9, 15));
    numberRangeSet.remove(Range.closed(3, 5));
    numberRangeSet.remove(Range.closed(7, 10));

    assertTrue(numberRangeSet.contains(1));
    assertFalse(numberRangeSet.contains(9));
    assertTrue(numberRangeSet.contains(12));
}

ご覧のとおり、削除した後も、セット内に残っている範囲項目のいずれかに存在する値にアクセスできます。

4.3. 範囲スパン

それでは、 RangeSet の全体的な範囲がどのようなものかを見てみましょう。

@Test
public void givenRangeSet__whenSpanIsCalled__returnsSucessfully() {
    RangeSet<Integer> numberRangeSet = TreeRangeSet.create();

    numberRangeSet.add(Range.closed(0, 2));
    numberRangeSet.add(Range.closed(3, 5));
    numberRangeSet.add(Range.closed(6, 8));
    Range<Integer> experienceSpan = numberRangeSet.span();

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

4.4. 部分範囲を取得する

与えられた Range に基づいて RangeSet の一部を取得したい場合は、 subRangeSet メソッドを使用できます。

@Test
public void
  givenRangeSet__whenSubRangeSetIsCalled__returnsSubRangeSucessfully() {

    RangeSet<Integer> numberRangeSet = TreeRangeSet.create();

    numberRangeSet.add(Range.closed(0, 2));
    numberRangeSet.add(Range.closed(3, 5));
    numberRangeSet.add(Range.closed(6, 8));
    RangeSet<Integer> numberSubRangeSet
      = numberRangeSet.subRangeSet(Range.closed(4, 14));

    assertFalse(numberSubRangeSet.contains(3));
    assertFalse(numberSubRangeSet.contains(14));
    assertTrue(numberSubRangeSet.contains(7));
}

4.5. 補完方法

次に、 complement メソッドを使用して、 RangeSet に存在するもの以外のすべての値を取得します。

@Test
public void givenRangeSet__whenComplementIsCalled__returnsSucessfully() {
    RangeSet<Integer> numberRangeSet = TreeRangeSet.create();

    numberRangeSet.add(Range.closed(0, 2));
    numberRangeSet.add(Range.closed(3, 5));
    numberRangeSet.add(Range.closed(6, 8));
    RangeSet<Integer> numberRangeComplementSet
      = numberRangeSet.complement();

    assertTrue(numberRangeComplementSet.contains(-1000));
    assertFalse(numberRangeComplementSet.contains(2));
    assertFalse(numberRangeComplementSet.contains(3));
    assertTrue(numberRangeComplementSet.contains(1000));
}

4.6. 範囲との交点

最後に、 RangeSet に存在する範囲区間が他の与えられた範囲の値の一部または全部と交差しているかどうかをチェックしたい場合は、 intersect メソッドを使用できます。

@Test
public void givenRangeSet__whenIntersectsWithinRange__returnsSucessfully() {
    RangeSet<Integer> numberRangeSet = TreeRangeSet.create();

    numberRangeSet.add(Range.closed(0, 2));
    numberRangeSet.add(Range.closed(3, 10));
    numberRangeSet.add(Range.closed(15, 18));

    assertTrue(numberRangeSet.intersects(Range.closed(4, 17)));
    assertFalse(numberRangeSet.intersects(Range.closed(19, 200)));
}

5結論

このチュートリアルでは、いくつかの例を使用してGuavaライブラリの RangeSet を示しました。 RangeSet は、値がセット内に存在する特定の範囲内にあるかどうかを確認するために主に使用されます。

これらの例の実装はhttps://github.com/eugenp/tutorials/tree/master/guava-collections[GitHubプロジェクト]にあります - これはMavenベースのプロジェクトです。そのまま実行します。