Set
не имеет смысла вызывать ==
для вашего типа, если нет столкновений значений. Я это красная сельдь.
Set
вызывает hash(into hasher: inout Hasher)
для ваших значений, а затем принимает модуль по размеру внутреннего массива набора. Результатом является индекс, по которому должно быть значение (если оно уже существует в наборе). Естественно, этот процесс позволяет нескольким значениям после хэширования и взятия по модулю оказаться в одном слоте массива.
Чтобы компенсировать это, вместо того, чтобы хранить элементы непосредственно в слотах массива, они хранятся в связанном списке. Концептуально предметы внутри одного слота называются «ведром». При поиске элемента Set
использует значение хеш-функции для поиска правильного сегмента, но для поиска точного элемента необходимо выполнить итерацию по связанному списку. На этом этапе хеши больше не используются для идентификации элементов, поэтому Set
использует ==
проверки, пока не найдет правильное совпадение. Это обычно довольно эффективно, потому что Set
должен сделать массив достаточно большим, чтобы сегменты были маленькими и содержали очень мало коллизий.
Поскольку нахождение элемента внутри корзины - это O(N)
, если вы можете вызвать много коллизий хэшей, тогда вы можете заставить Set
O(1)
операции вставки / удаления / проверки выродиться в O(N)
обходы над целые элементы Set
(поскольку вы можете сделать так, чтобы все элементы отображались в одно ведро. Чтобы противостоять уязвимости DOS, современные ассоциативные структуры данных используют «начальное число», которое выбирается случайным образом при каждом запуске приложения, и использовать его для шифрования. хэши. Таким образом, становится очень трудно создавать полезные нагрузки с одинаковыми значениями хеш-функции (что может вызвать проблему с большим размером сегмента.) Отсюда и ваш недетерминизм. См. PSA: stdlib теперь использует случайным образом хешированные значения .
По сути, Set<T>
- это просто Dictionary
типа [T: Void]
. Поэтому, если вы прочтете, как работают ассоциативные структуры данных на основе хеша (другие распространенные имена - словари, хеши, хэш-карты и т. Д.), Многое из этого применимо.