Guava – Sets – 番石榴 –套

最后修改: 2014年 11月 4日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’ll illustrate the most useful ways you can leverage Guava to work with Java Sets.

在本教程中,我们将说明最有用的方法,你可以利用Guava来处理Java集合

Let’s start very simple and create a HashSet without the new operator, using Guava:

让我们从非常简单的开始,使用Guava创建一个没有new操作符的HashSet

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

2. Union of Sets

2.集合的联合

First, let’s take a look at how we can do a union operation over Sets – using the simple Sets.union() API:

首先,让我们来看看我们如何对集合进行联合操作–使用简单的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. Cartesian Product of Sets

3.集合的笛卡尔积

We can also get the product of two sets using Sets.cartesianProduct() as in the following example:

我们也可以使用Sets.cartesianProduct()得到两个集合的乘积,如下例所示。

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

Note that – to be able to test out the result easily, we are using a Function and a Joiner to convert the complex Set<List<Character>> structure into a more manageable Iterable<String>.

请注意–为了能够轻松地测试出结果,我们使用了一个Function和一个Joiner来将复杂的Set<List<Character>>结构转换成一个更容易管理的Iterable<String>

4. Sets Intersection

4.设置交集

Next – let’s see how to get the intersection between two sets – using the Sets.intersection() API:

接下来–让我们看看如何获得两个集合的交集–使用Sets.intersection() API。

@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. Symmetric Difference of Sets

5.集合的对称性差异

Now, let’s have a look at the symmetric difference of two sets – all elements that are contained in either set 1 or set 2 but not in both:

现在,让我们来看看两个集合的对称性差异–包含在集合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. Power Set

6.力量集

Now – Let’s see how to calculate the power set – the set of all possible subsets of that set.

现在–让我们看看如何计算幂集–该集所有可能的子集的集合

In the following example – we use Sets.powerSet() to calculate the power set of a given set of characters:

在下面的例子中–我们使用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

7.ContiguousSet

Next – Let’s take a look at a sorted set of contiguous values – the ContiguousSet.

接下来–让我们看看一个排序的连续值集合–ContiguousSet

In the following example – we get a set of integers [10, 11, …, 30] into a 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());
}

This type of data structure is of course something you can do in plain Java with a TreeSet – but the semantics of this specialized type of set are just much more nicer to work with if you need your data represented this way.

当然,这种类型的数据结构你可以在普通的Java中用TreeSet来做–但是这种特殊类型的集合的语义要好得多,如果你需要你的数据以这种方式表示的话。

8. RangeSet

8.RangeSet

Now – let’s take a look at RangeSet. We can use RangeSet to hold disconnected and nonempty ranges.

现在–让我们看一下RangeSet。我们可以使用RangeSet来保存不连接的和非空的范围。

In the following example – when start with 2 disconnected ranges and then we connect them into a single, large range:

在下面的例子中–当从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());
}

Let’s go over this example in detail:

让我们详细了解一下这个例子:

  • First – we insert the 2 disconnected ranges: [1, 10] and [12, 15]
  • Next – we add a third range to connect the existing 2: [10, 12]
  • Finally – we verify that the RangeSet was smart enough to see that the 3 ranges are now one large range, and merge them together into: [1, 15]

9. MultiSet

9.多套

Next – let’s discuss how to use Multiset. As opposed to normal sets, a Multiset does support adding duplicate elements – which it counts as occurrences.

接下来–让我们讨论如何使用Multiset。与普通的集合相比,一个Multiset确实支持添加重复的元素–它把这些元素算作出现

In the following example – we go through some simple multi-set logic:

在下面的例子中–我们经历了一些简单的多集逻辑。

@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. Get Top N Elements in a MultiSet

10.获取一个多集合中的前N个元素

Now – let’s see a more complex and useful example of using a MultiSet. We’ll get the Top N occurring elements in the set – basically, the most common ones.

现在–让我们看看使用MultiSet的一个更复杂和有用的例子。我们将得到集合中的前N个出现的元素–基本上,最常见的元素。

In the following example – we sort the elements in the Multiset using Multisets.copyHighCountFirst():

在下面的例子中 – 我们使用Multiset.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. Conclusion

11.结论

In this quick tutorial we discussed the most common and useful usecases of working with Sets using the Guava library.

在这个快速教程中,我们讨论了使用Guava库处理Sets的最常见和最有用的情况

The implementation of all these examples and code snippets can be found in my Guava github project – this is an Eclipse based project, so it should be easy to import and run as it is.

所有这些例子和代码片段的实现可以在我的Guava github项目中找到 – 这是一个基于Eclipse的项目,所以它应该很容易导入和运行,如实。