**1. Overview**

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

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

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

**2. Union of Sets**

First, let's take a look at how we can **do a union operation over Sets** – using the simple *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**

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

```
@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>*.

**4. ***Sets* Intersection

*Sets*Intersection

Next – let's see how to get **the intersection between two sets** – using the *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

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:

```
@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**

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:

```
@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*

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

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

**8. ***RangeSet*

*RangeSet*

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

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

```
@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*

*MultiSet*

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**.

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*

*MultiSet*

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.

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

```
@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**

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

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.