Что объединяет структуры данных Dictionary и Set в Swift
Что проверяют
Знаете ли вы, что обе коллекции стандартной библиотеки построены на хешировании, и понимаете ли последствия: требование Hashable, значимую семантику и отсутствие гарантированного порядка.
Как отвечать
- Обе хранят элементы по хешу, поэтому ключ
Dictionaryи элементSetобязаны соответствоватьHashable. - Обе объявлены как
struct, то есть это значимые типы с копированием при записи: присваивание копирует ссылку на буфер, а реальное копирование происходит при первой мутации. - Порядок обхода не определён и может отличаться между запусками приложения, потому что в хеш подмешивается случайное зерно. Для стабильного вывода нужен явный
sorted. - Средняя сложность вставки, удаления и поиска O(1).
- Обе поддерживают
count,isEmpty,contains, обход вfor in, литеральную инициализацию.
Различия: словарь хранит пары и его подписка возвращает опциональное значение, множество хранит только элементы и умеет теоретико-множественные операции union, intersection, subtracting. Похожие операции доступны и для keys словаря.
struct User: Hashable { let id: Int; let name: String }
var seen: Set<User> = []
var byId: [Int: User] = [:]
seen.insert(user) // inserted == false, если такой уже есть
byId[user.id] = user // молча перезапишетГде спотыкаются
Реализуют == и hash(into:) по разным наборам полей. Контракт требует обратного: равные значения обязаны давать равный хеш, иначе элемент кладётся в одну корзину, а ищется в другой и «пропадает».
Второе: кладут ссылочный тип с изменяемыми свойствами, а потом меняют поле, участвующее в хеше. Объект остаётся на старом месте, contains возвращает false, а удалить его уже нечем.
Третье: рассчитывают на порядок. Печатают множество и ждут порядок добавления, строят список в SwiftUI прямо по словарю и получают скачущие ячейки. Если порядок важен, нужен массив или явная сортировка, а идентификаторы для ForEach должны быть стабильными.