1概要

このチュートリアルでは、Guavaを利用してJavaセットを扱うための最も有用な方法を説明します。

とても簡単に始めて、Guavaを使用して、新しい演算子なしで

HashSet

** を作成しましょう。

Set<String> aNewSet = Sets.newHashSet();


2セットの和集合

最初に、簡単な

Sets.union()

APIを使用して、どのように** 集合に対して和集合演算を実行できるかを見てみましょう。

@Test
public void whenCalculatingUnionOfSets__thenCorrect() {
    Set<Character> first = ImmutableSet.of('a', 'b', 'c');
    Set<Character> second = ImmutableSet.of('b', 'c', 'd');

    Set<Character> union = Sets.union(first, second);
    assertThat(union, containsInAnyOrder('a', 'b', 'c', 'd'));
}


3デカルト積集合

次の例のように

Sets.cartesianProduct()

を使用して** 2つのセットの積を取得することもできます。

@Test
public void whenCalculatingCartesianProductOfSets__thenCorrect() {
    Set<Character> first = ImmutableSet.of('a', 'b');
    Set<Character> second = ImmutableSet.of('c', 'd');
    Set<List<Character>> result =
      Sets.cartesianProduct(ImmutableList.of(first, second));

    Function<List<Character>, String> func =
      new Function<List<Character>, String>() {
        public String apply(List<Character> input) {
            return Joiner.on(" ").join(input);
        }
    };
    Iterable<String> joined = Iterables.transform(result, func);
    assertThat(joined, containsInAnyOrder("a c", "a d", "b c", "b d"));
}

注意してください – 結果を簡単にテストできるようにするために、

Function



Joiner

を使って、複雑な

Set <List <Character>>

構造をより管理しやすい

Iterable <String>

に変換しています。


4 __交差点

次に、

Sets.intersection()

APIを使用して、2つのセット間の共通部分を取得する方法を見てみましょう。

@Test
public void whenCalculatingSetIntersection__thenCorrect() {
    Set<Character> first = ImmutableSet.of('a', 'b', 'c');
    Set<Character> second = ImmutableSet.of('b', 'c', 'd');

    Set<Character> intersection = Sets.intersection(first, second);
    assertThat(intersection, containsInAnyOrder('b', 'c'));
}

5.集合の対称差

それでは、2つのセットの対称的な違いを見てみましょう。セット1とセット2のどちらにも含まれていて、両方には含まれていないすべての要素です。

@Test
public void whenCalculatingSetSymmetricDifference__thenCorrect() {
    Set<Character> first = ImmutableSet.of('a', 'b', 'c');
    Set<Character> second = ImmutableSet.of('b', 'c', 'd');

    Set<Character> intersection = Sets.symmetricDifference(first, second);
    assertThat(intersection, containsInAnyOrder('a', 'd'));
}


6. 電源セット

さて – パワーセット – そのセットのすべての可能なサブセットのセット** の計算方法を見てみましょう。

次の例では、

Sets.powerSet()

を使用して、特定の文字セットのべき乗セットを計算します。

@Test
public void whenCalculatingPowerSet__thenCorrect() {
    Set<Character> chars = ImmutableSet.of('a', 'b');

    Set<Set<Character>> result = Sets.powerSet(chars);

    Set<Character> empty =  ImmutableSet.<Character> builder().build();
    Set<Character> a = ImmutableSet.of('a');
    Set<Character> b = ImmutableSet.of('b');
    Set<Character> aB = ImmutableSet.of('a', 'b');

    assertThat(result, contains(empty, a, b, aB));
}


7.

連続セット


次に、ソートされた一連の連続した値、

ContiguousSet

を見てみましょう。

次の例では、一連の整数[10、11、…​、30]を

ContiguousSet

に入れます。

@Test
public void whenCreatingRangeOfIntegersSet__thenCreated() {
    int start = 10;
    int end = 30;
    ContiguousSet<Integer> set = ContiguousSet.create(
      Range.closed(start, end), DiscreteDomain.integers());

    assertEquals(21, set.size());
    assertEquals(10, set.first().intValue());
    assertEquals(30, set.last().intValue());
}

この種のデータ構造はもちろん

TreeSet

を使って普通のJavaでできることです – しかし、このように表現されたデータが必要な場合は、

この特殊なタイプの集合のセマンティクスがよりうまく機能します


8

RangeSet


それでは、

RangeSet

を見てみましょう。

RangeSet

を使用して、接続されていない空でない範囲を保持できます。

次の例では – 2つの接続されていない範囲から始めて、次にそれらを単一の大きな範囲に接続します。

@Test
public void whenUsingRangeSet__thenCorrect() {
    RangeSet<Integer> rangeSet = TreeRangeSet.create();
    rangeSet.add(Range.closed(1, 10));
    rangeSet.add(Range.closed(12, 15));

    assertEquals(2, rangeSet.asRanges().size());

    rangeSet.add(Range.closed(10, 12));
    assertTrue(rangeSet.encloses(Range.closed(1, 15)));
    assertEquals(1, rangeSet.asRanges().size());
}

この例を詳しく見ていきましょう:

  • 最初に – 2つの切り離された範囲を挿入します:

    [1、10]



    [12、15]

  • 次に – 既存の2を接続するために3番目の範囲を追加します。

    [10、12]

  • 最後に、

    RangeSet

    がそれを確認するのに十分スマートであることを確認します。

3つの範囲は1つの大きな範囲になり、それらをマージして

[1、15]

にします。


9

マルチセット


次に –

Multiset

の使い方を説明しましょう。通常の集合とは対照的に、

Multiset

は重複要素の追加をサポートしています – これはオカレンスとしてカウントされます** 。

次の例では – 私たちはいくつかの簡単なマルチセットロジックを見ていきます。

@Test
public void whenInsertDuplicatesInMultiSet__thenInserted() {
    Multiset<String> names = HashMultiset.create();
    names.add("John");
    names.add("Adam", 3);
    names.add("John");

    assertEquals(2, names.count("John"));
    names.remove("John");
    assertEquals(1, names.count("John"));

    assertEquals(3, names.count("Adam"));
    names.remove("Adam", 2);
    assertEquals(1, names.count("Adam"));
}


10

MultiSet


の上位N個の要素を取得する

それでは、

MultiSet

を使用した、より複雑で便利な例を見てみましょう。

セット内の上位N個の出現要素を取得します – 基本的に、最も一般的な要素

次の例では、

Multisets.copyHighCountFirst()

を使用して

Multiset

内の要素を並べ替えます。

@Test
public void whenGetTopOcurringElementsWithMultiSet__thenCorrect() {
    Multiset<String> names = HashMultiset.create();
    names.add("John");
    names.add("Adam", 5);
    names.add("Jane");
    names.add("Tom", 2);

    Set<String> sorted = Multisets.copyHighestCountFirst(names).elementSet();
    List<String> sortedAsList = Lists.newArrayList(sorted);
    assertEquals("Adam", sortedAsList.get(0));
    assertEquals("Tom", sortedAsList.get(1));
}


11結論

この簡単なチュートリアルでは、Guavaライブラリを使用したSetでの作業** の最も一般的で便利な使用例について説明しました。

これらすべての例とコードスニペットの実装はhttps://github.com/eugenp/tutorials/tree/master/guava-collections[my Guava github project]** にあります。インポートしてそのまま実行するのは簡単なはずです。