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ベースのプロジェクトです。そのまま実行します。