Всегда ли Set в Swift гарантирует уникальность элементов?

«Всегда ли Set в Swift гарантирует уникальность элементов?» — вопрос из категории Swift Core, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Нет, не всегда. Set гарантирует уникальность элементов, но эта гарантия зависит от корректной реализации протоколов Hashable и Equatable для типа элемента.

Как это работает:

  1. Set использует hashValue для быстрого поиска элемента в бакете.
  2. Если хэши совпадают, вызывается оператор == для точной проверки равенства.

Проблема возникает при некорректной реализации: если hash(into:) и == используют не все значимые свойства объекта, разные объекты могут считаться одинаковыми, и Set их отбросит.

Пример некорректной реализации:

struct User: Hashable {
    let id: Int
    let name: String

    // ОШИБКА: Сравнение только по имени, игнорируется `id`
    static func == (lhs: User, rhs: User) -> Bool {
        return lhs.name == rhs.name
    }

    func hash(into hasher: inout Hasher) {
        hasher.combine(name) // Хэшируется только имя
    }
}

let userSet: Set<User> = [
    User(id: 1, name: "Alex"),
    User(id: 2, name: "Alex") // Set воспримет это как дубликат и оставит только одного "Alex"
]
print(userSet.count) // 1, хотя id разные

Best Practice: Всегда включайте в hash(into:) и == все свойства, определяющие уникальность экземпляра.