Класс Java HashSet реализует интерфейс Set, поддерживаемый хэш-таблицей(фактически экземпляром HashMap ). Он не дает никаких гарантий относительно порядка итерации и допускает нулевой элемент.
1. Иерархия HashSet
Класс HashSet расширяет класс AbstractSet, который реализует интерфейс Set. Интерфейс Set наследует интерфейсы Collection и Iterable в иерархическом порядке.
public class HashSet<E> extends AbstractSet<E>implements Set<E>, Cloneable, Serializable{//implementation}

2. Возможности HashSet
- Он реализует Set Interface.
- В HashSet не допускаются повторяющиеся значения.
- В HashSet допускается один элемент NULL.
- Это неупорядоченная коллекция, которая не дает никаких гарантий относительно порядка итераций набора.
- Этот класс обеспечивает постоянную производительность по времени для основных операций(добавление, удаление, содержание и размер).
- HashSet не синхронизирован. Если несколько потоков одновременно обращаются к набору хэшей и хотя бы один из потоков изменяет набор, он должен быть синхронизирован извне.
- Используйте метод Collections.synchronizedSet(new HashSet()) для получения синхронизированного хэш-набора.
- Итераторы, возвращаемые методом итератора этого класса, являются отказоустойчивыми и могут выдать исключение ConcurrentModificationException, если набор будет изменен в любое время после создания итератора любым способом, кроме как с помощью собственного метода итератора remove().
- HashSet также реализует интерфейсы Searlizable и Cloneable.
2.1 Начальная мощность
Начальная емкость означает количество корзин(в резервной HashMap) при создании hashset. Количество корзин будет автоматически увеличено, если текущий размер заполнится.
Начальная емкость по умолчанию — 16. Мы можем переопределить эту емкость по умолчанию, передав емкость по умолчанию в его конструкторе HashSet(int initialCapacity).
2.2 Коэффициент нагрузки
Коэффициент загрузки — это мера того, насколько HashSet может быть заполнен, прежде чем его емкость автоматически увеличится. Коэффициент загрузки по умолчанию — 0,75.
Это называется порогом и равно(DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY). Когда количество элементов HashSet превышает этот порог, размер HashSet изменяется, и новая емкость вдвое превышает предыдущую.
С HashSet по умолчанию внутренняя емкость составляет 16, а коэффициент загрузки — 0,75. Количество сегментов автоматически увеличится, когда в таблице будет 12 элементов.
3. Конструкторы HashSet
HashSet имеет четыре типа конструкторов:
- HashSet(): инициализирует экземпляр HashSet по умолчанию с начальной емкостью по умолчанию(16) и коэффициентом загрузки по умолчанию(0,75).
- HashSet(int capacity): инициализирует HashSet с указанной емкостью и коэффициентом загрузки по умолчанию(0,75).
- HashSet(int capacity, float loadFactor): инициализирует HashSet с указанной начальной емкостью и указанным коэффициентом загрузки.
- HashSet(Collection c): инициализирует HashSet с теми же элементами, что и указанная коллекция.
4. Методы HashSet
- public boolean add(E e) : добавляет указанный элемент в Set, если его еще нет. Этот метод внутренне использует метод equals() для проверки на наличие дубликатов. Если элемент дубликат, то элемент отклоняется, а значение НЕ заменяется.
- public void clear() : удаляет все элементы из хэш-набора.
- public boolean contains(Object o) : возвращает true, если хэш-набор содержит указанный элемент, в противном случае возвращает false.
- public boolean isEmpty() : возвращает true, если hashset не содержит ни одного элемента, в противном случае false.
- public int size() : возвращает количество элементов в хэш-наборе.
- public Iterator<E> iterator() : возвращает итератор по элементам в этом хэш-наборе. Элементы возвращаются из iterator в произвольном порядке.
- public boolean remove(Object o) : удаляет указанный элемент из хэш-набора, если он присутствует, и возвращает true, в противном случае возвращает false.
- public boolean removeAll(Collection<?> c) : удалить все элементы в хэш-наборе, которые являются частью указанной коллекции.
- public Object clone() : возвращает поверхностную копию хэш-набора.
- public Spliterator<E> spliterator() : создает Spliterator с поздним связыванием и быстрым отказоустойчивым решением для элементов в этом хэш-наборе.
5. Пример Java HashSet
5.1. Пример добавления, удаления итератора HashSet
//1. Create HashSetHashSet<String> hashSet = new HashSet<>();//2. Add elements to HashSethashSet.add("A");hashSet.add("B");hashSet.add("C");hashSet.add("D");hashSet.add("E");System.out.println(hashSet);//3. Check if element existsboolean found = hashSet.contains("A"); //trueSystem.out.println(found);//4. Remove an elementhashSet.remove("D");//5. Iterate over valuesIterator<String> itr = hashSet.iterator();while(itr.hasNext()){String value = itr.next();System.out.println("Value: " + value);}
Вывод программы.
[A, B, C, D, E]trueValue: AValue: BValue: CValue: E
5.2 Пример преобразования HashSet в массив
Пример Java для преобразования хэш-набора в массив с помощью метода toArrray().
HashSet<String> hashSet = new HashSet<>();hashSet.add("A");hashSet.add("B");hashSet.add("C");hashSet.add("D");hashSet.add("E");String[] values = new String[hashSet.size()];hashSet.toArray(values);System.out.println(Arrays.toString(values));
Вывод программы.
[A, B, C, D, E]
5.3 Пример преобразования HashSet в ArrayList
Пример Java для преобразования хэш-набора в массив с использованием потокового API Java 8.
HashSet<String> hashSet = new HashSet<>();hashSet.add("A");hashSet.add("B");hashSet.add("C");hashSet.add("D");hashSet.add("E");List<String> valuesList = hashSet.stream().collect(Collectors.toList());System.out.println(valuesList);
Вывод программы.
[A, B, C, D, E]
6. Варианты использования HashSet
HashSet очень похож на класс ArrayList. Он дополнительно ограничивает дублирующиеся значения. Поэтому, когда у нас есть требование, где мы хотим хранить только отдельные элементы, мы можем выбрать HashSet.
Реальным вариантом использования HashSet может быть хранение данных из потока, где поток может содержать дублирующиеся записи, а нас интересуют только отдельные записи.
Другим вариантом использования может быть поиск отдельных слов в заданном предложении.
7. Производительность Java HashSet
- Класс HashSet обеспечивает постоянную производительность O(1) для основных операций(добавление, удаление, содержание и определение размера), предполагая, что хэш-функция правильно распределяет элементы по контейнерам.
- Итерация по этому набору требует времени, пропорционального сумме размера экземпляра HashSet(количество элементов) плюс «емкость» поддерживающего экземпляра HashMap(количество бакетов). Таким образом, очень важно не устанавливать начальную емкость слишком высокой(или коэффициент загрузки слишком низким), если важна производительность итерации.
8. Заключение
Из вышеизложенного обсуждения очевидно, что HashSet — очень полезный класс коллекции в случаях, когда мы хотим обрабатывать дубликаты записей. Он обеспечивает предсказуемую производительность для базовых операций.
Пишите мне в комментариях ваши вопросы, связанные с HashSet в Java.
Ссылка: