Ответ
Коллизия хэшей (одинаковый хэш у разных объектов) — нормальная ситуация, которую хэш-таблицы (как Dictionary или Set) умеют обрабатывать.
Механизм работы:
- Хэш-функция вычисляет индекс корзины (bucket) в таблице.
- Если в эту корзину уже помещен другой элемент, возникает коллизия.
- Swift разрешает коллизии, используя цепочки или открытую адресацию, храня оба объекта в одной корзине.
- Для точного определения нужного объекта используется проверка равенства (
==).
Пример коллизии:
struct Book: Hashable {
let isbn: String // Уникальный идентификатор
let title: String
// Намеренно «плохая» хэш-функция, использующая только длину названия
func hash(into hasher: inout Hasher) {
hasher.combine(title.count) // У «Swift» и «Kotlin» хэш будет одинаковым (длина 5)
}
static func == (lhs: Book, rhs: Book) -> Bool {
// Для равенства важен isbn
return lhs.isbn == rhs.isbn
}
}
let book1 = Book(isbn: "123", title: "Swift") // Хэш для длины 5
let book2 = Book(isbn: "456", title: "Kotlin") // Хэш для длины 5 -> КОЛЛИЗИЯ
var library = Set<Book>()
library.insert(book1)
library.insert(book2) // Оба объекта будут добавлены, так как isbn разные.
Последствия:
- Корректность: Логика программы не нарушается, если правильно реализованы
hash(into:)и==. - Производительность: Частые коллизии ухудшают производительность с
O(1)доO(n)в худшем случае, так как поиск внутри корзины становится линейным.