Set (множество) в Swift - это неупорядоченная коллекция уникальных элементов. Для определения уникальности элементов Set использует два механизма:
Hashable
Equatable
Когда два объекта имеют одинаковое хэш-значение, но не равны между собой, происходит следующее:
==
)struct Person: Hashable {
let id: Int
let name: String
// Реализация Hashable
func hash(into hasher: inout Hasher) {
hasher.combine(id) // Используем только id для хэширования
}
// Реализация Equatable
static func == (lhs: Person, rhs: Person) -> Bool {
return lhs.id == rhs.id && lhs.name == rhs.name
}
}
let person1 = Person(id: 1, name: "Alice")
let person2 = Person(id: 1, name: "Bob") // Тот же id, но другое имя
var peopleSet = Set<Person>()
peopleSet.insert(person1)
peopleSet.insert(person2)
print(peopleSet.count) // Что будет?
Если объекты равны (== возвращает true):
Если объекты не равны (== возвращает false):
Swift использует метод цепочки для разрешения коллизий:
struct CollidingHash: Hashable {
let value: Int
// Намеренно создаем коллизии
func hash(into hasher: inout Hasher) {
hasher.combine(1) // Все объекты имеют одинаковый хэш
}
static func == (lhs: CollidingHash, rhs: CollidingHash) -> Bool {
return lhs.value == rhs.value
}
}
var set = Set<CollidingHash>()
set.insert(CollidingHash(value: 1))
set.insert(CollidingHash(value: 2)) // Добавится, т.к. != первому
print(set.count) // Выведет 2
func hash(into hasher: inout Hasher) {
hasher.combine(property1)
hasher.combine(property2)
}
Hashable
и Equatable
критически важнаГлавное: одинаковый хэш не означает замену элемента в Set, если объекты не равны согласно протоколу Equatable.