1. 概要

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

非常に簡単に始めて、Guavaを使用して、新しい演算子なしでHashSetを作成しましょう。

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

2. セットの和集合

まず、単純な Sets.union() APIを使用して、Setsに対して和集合演算を実行する方法を見てみましょう。

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

注–結果を簡単にテストできるように、 関数ジョイナー複合体を変換するには設定 >> より管理しやすい構造反復可能

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

次へ–並べ替えられた連続する値のセット– ContiguousSetを見てみましょう。

次の例では、整数のセット[10、11、…、30]をContinuousSetに取得します。

@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つの切断された範囲から始めて、それらを1つの大きな範囲に接続します。

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

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

  • 最初に– [1、10][12、15]の2つの切断された範囲を挿入します
  • 次に–既存の2を接続するための3番目の範囲を追加します: [10、12]
  • 最後に、 RangeSet が十分にスマートであり、3つの範囲が1つの大きな範囲になったことを確認し、それらを [1、15]にマージします。

9. マルチセット

次へ–マルチセットの使用方法について説明しましょう。 通常のセットとは対照的に、マルチセットは重複要素の追加をサポートします-これはオカレンスとしてカウントされます

次の例では、いくつかの単純なマルチセットロジックを実行します。

@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ライブラリを使用したセットの操作の最も一般的で便利なユースケースについて説明しました。

これらすべての例とコードスニペットの実装は、私のGuava githubプロジェクトにあります。これはEclipseベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。