Что такое Set, его особенности, зачем нужен и какие есть реализации
Что проверяют
Понимаете ли вы, как Set определяет уникальность и чем реально различаются реализации, а не только «в сете нет дублей». Следом обычно спрашивают, что будет с объектом без hashCode() в HashSet или как HashSet устроен внутри.
Как отвечать
Set это коллекция без повторов. Он нужен, когда важен сам факт наличия: видели ли уже этот id, убрать дубли, найти пересечение выборок через retainAll(). contains() у хэшевой реализации в среднем O(1) против O(n) у ArrayList.
HashSet: внутри обычныйHashMap, элемент кладётся ключом, значение общая заглушка. Порядок не гарантирован, допускается одинnull;LinkedHashSet: наследникHashSetсо связным списком поверх, хранит порядок вставки;TreeSet: красно-чёрное дерево наTreeMap, элементы отсортированы, операции O(log n), методыNavigableSet:floor(),ceiling(),subSet();EnumSet: битовая маска, самый быстрый и компактный вариант для перечислений;- потокобезопасные:
ConcurrentHashMap.newKeySet(),ConcurrentSkipListSetдля сортированного,CopyOnWriteArraySetдля маленьких редко меняющихся наборов; - неизменяемые:
Set.of()с Java 9 иSet.copyOf()с Java 10.nullне принимают, аSet.of()бросает исключение на дубликат в аргументах.
С Java 21 LinkedHashSet и SortedSet реализуют SequencedCollection: появились getFirst(), getLast(), reversed().
Уникальность проверяется по-разному: HashSet смотрит hashCode(), затем equals(), а TreeSet только compareTo() или переданный Comparator.
Где спотыкаются
Переопределяют equals() без hashCode(). Равные объекты попадают в разные корзины, и в HashSet появляются «дубликаты».
Меняют поле, от которого зависит hashCode(), уже после добавления. Элемент остаётся в старой корзине, contains() возвращает false, а remove() его не находит.
Передают в TreeSet компаратор, несогласованный с equals(), например сравнение людей по возрасту. Ровесники считаются одним элементом и молча теряются. Рядом ошибка с Set.of(): порядок обхода у него не гарантирован и может меняться от запуска к запуску.