Интерфейс Set расширяет интерфейс Collection и представляет набор уникальных элементов. Set почти не добавляет
новых методов, только вносит изменения в унаследованные. В частности, метод add() добавляет элемент в коллекцию и возвращает true,
если в коллекции еще нет такого элемента.
Добавленных методов в Set следует отметить следующие два статических метода:
static <E> Set<E>of(E... elements): возвращает неизменяемый набор из элементов elements
static <E> Set<E>copyOf(Collection<? extends E> col): возвращает неизменяемый набор, в которую добавляет все элементы коллекции col
Например, используем метод of() для создания набора:
import java.util.Set;
public class Program{
public static void main(String[] args) {
Set<String> people = Set.<String>of("Tom", "Bob", "Sam");
System.out.println(people); // [Tom, Sam, Bob]
}
}
Метод Set.of() создает неизменяемый набор типа class java.util.ImmutableCollections$SetN.
Отличительной особенностью наборов является то, что все элементы в нем должны быть уникальными. Для сравнения на равенстро применяется метод equals(), который имеют все классы. Так, если мы попробуем добавить в набор два одинаковых значения, то при выполнении будет сгенерирована ошибка:
import java.util.Set;
public class Program{
public static void main(String[] args) {
Set<String> people = Set.<String>of("Tom", "Bob", "Sam", "Tom"); // Ошибка! duplicate element: Tom
System.out.println(people);
}
}
Расспространенной реализацией интерфейса Set является обобщенный класс HashSet, который представляет хеш-таблицу. Если быть точнее, он наследует свой
функционал от класса AbstractSet, который, в свою очередь, реализует интерфейс Set.
Хеш-таблица представляет такую структуру данных, в которой все объекты имеют уникальный ключ или хеш-код. Данный ключ позволяет уникально идентифицировать объект в
таблице. Хеш-код представляет целое число, которое хеш-таблица вычисляет для каждого добавляемого объекта с помощью его метода hashCode(). Хеш-код обычно выводится из полей экземпляра объекта, предпочтительно таким образом,
чтобы объекты с разными данными давали разные коды. И также важно, чтобы хэш-коды вычислялись быстро, и чтобы вычисление зависело только от состояния объекта, который необходимо хэшировать.
Для создания объекта HashSet можно воспользоваться одним из следующих конструкторов:
HashSet(): создает пустой список
HashSet(Collection<? extends E> col): создает хеш-таблицу, в которую добавляет все элементы коллекции col
HashSet(int capacity): параметр capacity указывает начальную емкость таблицы, которая по умолчанию равна 16
HashSet(int capacity, float koef): параметр koef или коэффициент заполнения, значение которого должно быть в пределах от 0.0 до 1.0, указывает,
насколько должна быть заполнена емкость объектами прежде чем произойдет ее расширение. Например, коэффициент 0.75 указывает, что при заполнении
емкости на 3/4 произойдет ее расширение.
Создание хеш-таблицы:
import java.util.HashSet;
public class Program{
public static void main(String[] args) {
HashSet<String> langs = new HashSet<String>();
}
}
Создание хеш-таблицы по имеющейся коллекции (из неизменяемого набора):
import java.util.Set;
import java.util.HashSet;
public class Program{
public static void main(String[] args) {
Set<String> data = Set.<String>of("Java", "JavaScript", "C#");
HashSet<String> langs = new HashSet<String>(data);
System.out.println(langs); // [C#, Java, JavaScript]
}
}
Класс HashSet в основном реализует те методы, которые объявлены в родительских классах и применяемых интерфейсах. Приведу основные методы HashSet:
boolean add(E e): Добавляет указанный элемент в этот набор, если он ещё отсутствует
void clear(): Удаляет все элементы из этого набора
Object clone(): Возвращает поверхностную копию данного экземпляра HashSet: сами элементы не клонируются
boolean contains(Object o): Возвращает true, если этот набор содержит указанный элемент
boolean isEmpty(): Возвращает true, если этот набор не содержит элементов
Iterator<E> iterator(): Возвращает итератор по элементам этого набора
static <T> HashSet<T> newHashSet(int numElements): Создаёт новый пустой HashSet, подходящий для ожидаемого количества элементов
boolean remove(Object o): Удаляет указанный элемент из этого набора, если он присутствует
int size(): Возвращает количество элементов в этом наборе
Object[] toArray(): Возвращает массив, содержащий все элементы этой коллекции
С помощью метода add() можно добавить новый объект в хеш-таблицу. Если такого элемента еще нет, то объект добавляется, а метод возвращает true. Если элемент уже есть, ничего не происходит, а метод возвращает
false:
import java.util.HashSet;
public class Program{
public static void main(String[] args) {
HashSet<String> langs = new HashSet<String>();
// добавим ряд объектов
langs.add("Java");
langs.add("C++");
langs.add("C#");
// пытаемся добавить элемент, который уже есть в коллекции
boolean isAdded = langs.add("Java");
System.out.println(isAdded); // false
System.out.printf("langs size: %d \n", langs.size()); // langs size: 3
System.out.println(langs); // [C#, Java, C++]
}
}
Метод remove() удаляет объект из хеш-таблицы. ПРи успешном удалении метод возвращает true. Если объект отсутствует, ничего не происходит, а метод возвращает
false. Для полного же удаления всех элементов применяется метод clear(). Пример удаления:
import java.util.Set;
import java.util.HashSet;
public class Program{
public static void main(String[] args) {
Set<String> data = Set.<String>of("Java", "JavaScript", "C#", "Python");
HashSet<String> langs = new HashSet<String>(data);
// удаляем язык JavaScript
boolean isRemoved = langs.remove("JavaScript");
System.out.println("JavaScript removed: " + isRemoved); // true
// удаляем язык OCalm
isRemoved = langs.remove("OCalm");
System.out.println("OCalm removed: " + isRemoved); // false
System.out.println(langs); // [C#, Java, Python]
// удаляем все
langs.clear();
System.out.println(langs); // []
}
}