Чтобы решить этот вопрос, я поиграл с пользовательской структурой, которая реализует протокол Hashable. Я пытаюсь увидеть, сколько раз вызывается перегрузка оператора эквивалентности (==
) в зависимости от того, есть ли коллизия хешей или нет при заполнении Dictionary
.
Обновить
@matt написал гораздо более чистый пример пользовательской структуры, которая реализует протокол Hashable и показывает, как часто hashValue
и ==
. Я копирую его код ниже. Чтобы увидеть мой оригинальный пример, посмотрите историю изменений.
struct S : Hashable {
static func ==(lhs:S,rhs:S) -> Bool {
print("called == for", lhs.id, rhs.id)
return lhs.id == rhs.id
}
let id : Int
var hashValue : Int {
print("called hashValue for", self.id)
return self.id
}
init(_ id:Int) {self.id = id}
}
var s = Set<S>()
for i in 1...5 {
print("inserting", i)
s.insert(S(i))
}
Это дает результаты:
/*
inserting 1
called hashValue for 1
inserting 2
called hashValue for 2
called == for 1 2
called hashValue for 1
called hashValue for 2
inserting 3
called hashValue for 3
inserting 4
called hashValue for 4
called == for 3 4
called == for 1 4
called hashValue for 2
called hashValue for 3
called hashValue for 1
called hashValue for 4
called == for 3 4
called == for 1 4
inserting 5
called hashValue for 5
*/
Поскольку Hashable использует Equatable для различения хеш-коллизий (я так или иначе предполагаю), я ожидаю, что func ==()
будет вызываться только при хеш-коллизиях. Тем не менее, в примере @matt выше нет коллизий хешей, и все же вызывается ==
. В других моих экспериментах по форсированию коллизий хешей (см. Этот вопрос редактирования истории) ==
казалось случайным числом раз.
Что здесь происходит?