1. введение
Набор – это удобный способ представить уникальную коллекцию предметов.
В этом уроке мы узнаем больше о том, что это значит и как мы можем использовать его в Java.
2. Немного теории множеств
2.1. Что Такое Набор?
Набор-это просто группа уникальных вещей. Итак, существенной характеристикой любого набора является то, что он не содержит дубликатов .
Мы можем поместить в набор все, что захотим. Однако мы обычно используем наборы для группировки вещей, которые имеют общую черту. Например, у нас может быть набор транспортных средств или набор животных.
Давайте используем два набора целых чисел в качестве простого примера:
setA : {1, 2, 3, 4} setB : {2, 4, 6, 8}
Мы можем показать наборы в виде диаграммы, просто поместив значения в круги:
Подобные диаграммы известны как диаграммы Венна и дают нам полезный способ показать взаимодействие между наборами, как мы увидим позже.
2.2. Пересечение множеств
Термин пересечение означает общие значения различных множеств .
Мы видим, что целые числа 2 и 4 существуют в обоих наборах. Таким образом, пересечение setA и setB равно 2 и 4, потому что это значения, которые являются общими для обоих наших наборов.
setA intersection setB = {2, 4}
Чтобы показать пересечение на диаграмме, мы объединяем наши два набора и выделяем область, общую для обоих наших наборов:
2.3. Объединение множеств
Термин объединение означает объединение значений различных наборов .
Итак, давайте создадим новый набор, который является объединением наших наборов примеров. Мы уже знаем, что у нас не может быть повторяющихся значений в наборе. Однако наши наборы имеют некоторые повторяющиеся значения (2 и 4). Поэтому, когда мы объединяем содержимое обоих наборов, нам нужно убедиться, что мы удалили дубликаты. Таким образом, мы получаем 1, 2, 3, 4, 6 и 8.
setA union setB = {1, 2, 3, 4, 6, 8}
Опять же, мы можем показать объединение на диаграмме. Итак, давайте объединим наши два набора и выделим область, которая представляет объединение:
2.4. Относительное дополнение множеств
Термин относительное дополнение означает значения из одного набора, которых нет в другом . Это также называется разницей в наборе.
Теперь давайте создадим новые наборы, которые являются относительными дополнениями наборов и setB .
relative complement of setA in setB = {6, 8} relative complement of setB in setA = {1, 3}
А теперь давайте выделим область в zeta , которая не является частью set B . Это дает нам относительное дополнение set in set A :
2.5. Подмножество и Надмножество
Подмножество-это просто часть большего набора, и больший набор называется надмножеством. Когда у нас есть подмножество и надмножество, объединение этих двух равно надмножеству, а пересечение равно подмножеству.
3. Реализация Операций Набора С java.util.Set
Чтобы увидеть, как мы выполняем операции с наборами в Java, мы возьмем примеры наборов и реализуем пересечение, объединение и относительное дополнение. Итак, давайте начнем с создания наших выборочных наборов целых чисел:
private SetsetA = setOf(1,2,3,4); private Set setB = setOf(2,4,6,8); private static Set setOf(Integer... values) { return new HashSet (Arrays.asList(values)); }
3.1. Пересечение
Во-первых, мы собираемся использовать метод retainAll для создания пересечения наших выборочных наборов . Поскольку retainAll изменяет набор напрямую, мы сделаем копию setA под названием intersectSet. Затем мы будем использовать метод retainAll , чтобы сохранить значения, которые также находятся в set B :
SetintersectSet = new HashSet<>(setA); intersectSet.retainAll(setB); assertEquals(setOf(2,4), intersectSet);
3.2. Союз
Теперь давайте используем метод addAll для создания объединения наших наборов образцов . Метод addAll добавляет все элементы поставляемого набора в другой. Опять же, поскольку add All обновляет набор напрямую, мы сделаем копию setA под названием union Set , а затем добавим к нему sub :
SetunionSet = new HashSet<>(setA); unionSet.addAll(setB); assertEquals(setOf(1,2,3,4,6,8), unionSet);
3.3. Относительное дополнение
Наконец, мы будем использовать метод removeAll для создания относительного дополнения set B в set A . Мы знаем, что нам нужны значения, которые находятся в множествах , которые не существуют в множестве B . Поэтому нам просто нужно удалить все элементы из наборов , которые также находятся в наборе B :
SetdifferenceSet = new HashSet<>(setA); differenceSet.removeAll(setB); assertEquals(setOf(1,3), differenceSet);
4. Реализация операций набора с потоками
4.1. Пересечение
Давайте создадим пересечение наших множеств с помощью Потоков .
Во-первых, мы получим значения из setA в поток. Затем мы отфильтруем поток, чтобы сохранить все значения, которые также находятся в set B . И, наконец, мы соберем результаты в новый Набор :
SetintersectSet = setA.stream() .filter(setB::contains) .collect(Collectors.toSet()); assertEquals(setOf(2,4), intersectSet);
4.2. Союз
Теперь давайте используем статический метод Streams.concat , чтобы добавить значения наших наборов в один поток .
Чтобы получить объединение из объединения наших наборов, нам нужно удалить все дубликаты. Мы сделаем это, просто собрав результаты в Набор :
SetunionSet = Stream.concat(setA.stream(), setB.stream()) .collect(Collectors.toSet()); assertEquals(setOf(1,2,3,4,6,8), unionSet);
4.3. Относительное Дополнение
Наконец, мы создадим относительное дополнение set B в set A .
Как и в примере с пересечением, мы сначала получим значения из set в поток. На этот раз мы отфильтруем поток, чтобы удалить все значения, которые также находятся в set B . Затем мы соберем результаты в новый Набор :
SetdifferenceSet = setA.stream() .filter(val -> !setB.contains(val)) .collect(Collectors.toSet()); assertEquals(setOf(1,3), differenceSet);
5. Служебные библиотеки для операций набора
Теперь, когда мы увидели, как выполнять базовые операции набора с помощью чистой Java, давайте использовать несколько служебных библиотек для выполнения тех же операций. Одна приятная вещь в использовании этих библиотек заключается в том, что имена методов четко сообщают нам, какая операция выполняется.
5.1. Зависимости
Чтобы использовать коллекции Guava Sets и Apache Commons SetUtils , нам нужно добавить их зависимости:
com.google.guava guava 27.1-jre org.apache.commons commons-collections4 4.3
5.2. Наборы Гуавы
Давайте используем класс Guava Sets для выполнения пересечения и объединения на наших примерах наборов. Для этого мы можем просто использовать статические методы union и intersection класса Sets :
SetintersectSet = Sets.intersection(setA, setB); assertEquals(setOf(2,4), intersectSet); Set unionSet = Sets.union(setA, setB); assertEquals(setOf(1,2,3,4,6,8), unionSet);
Взгляните на нашу статью о наборах гуавы, чтобы узнать больше.
5.3. Коллекции Apache Commons
Теперь давайте использовать статические методы intersection и union класса SetUtils из коллекций Apache Commons:
SetintersectSet = SetUtils.intersection(setA, setB); assertEquals(setOf(2,4), intersectSet); Set unionSet = SetUtils.union(setA, setB); assertEquals(setOf(1,2,3,4,6,8), unionSet);
Чтобы узнать больше, ознакомьтесь с нашим учебником по Apache Commons Collections SetUtils.
6. Заключение
Мы видели обзор того, как выполнять некоторые основные операции с наборами, а также подробную информацию о том, как реализовать эти операции различными способами.
Все примеры кода можно найти на GitHub .