Чтобы проверить, нет ли элемента в очень большом списке, вы можете использовать Фильтр Блума . Это обобщение хеш-таблицы, которая генерирует для каждой входной строки список хешей, которые хранятся в отличие от хеш-таблицы в нескольких сегментах. Таким образом, если у вас есть одна коллизия хеш-значений, она все равно может сработать, проверив другие хэши, если эта точная строка была когда-либо добавлена.
У вас все еще могут быть ложные срабатывания (filter.Contains ("xxxx") возвращает истину, хотя она никогда не добавлялась в список), но никогда не ложные отрицания.
Регулируя емкость, вы можете настроить частоту появления ошибок. Если ваш фильтр может жить с небольшим количеством ложных срабатываний, то этот должен быть хорошим.
Для примера посмотрите этот .
Я попробовал несколько попыток. Большинство реализаций используют ссылки в своем классе узлов, что невероятно неэффективно для памяти.
Один из них на SO выглядит довольно неплохо: Как создать trie в c # . Этот спасает ок. 30% по сравнению с простым списком.
Помимо структур данных, я думаю, вам нужно взглянуть на общую цель. Я предполагаю, что ваши фактические данные не являются адресами электронной почты, потому что фильтр спама - это давно решенная проблема. Но чтобы поиграть с вашим примером, в ваших данных есть структура, которой вы можете воспользоваться. У вас есть большой список, состоящий из имени и домена. Первое, что нужно сделать, это разделить ваши данные на более мелкие файлы, которые содержат только почтовые адреса одного домена. Затем вы сортируете по имени и создаете индекс для каждого домена, где начальная позиция файла для каждой буквы хранится в его заголовке.
Когда приходит новое письмо, вы можете сначала выполнить быструю предварительную проверку с помощью фильтра Блума. Если он говорит, что он чистый, то вы закончили уже в 99,5% случаев. Почему 99,5%? Вы можете настроить свой фильтр Блума, чтобы иметь это свойство, рассчитав, сколько памяти вы хотите потратить, чтобы получить эту точность.
Это замечательно с точки зрения системы, потому что теперь вы можете сознательно принять решение о том, сколько ресурсов памяти / ЦП / диска вы хотите потратить на эту задачу.
Если у вас есть совпадение, вы можете открыть индексированный файл для этого домена, сразу перейти к отсортированным почтовым адресам и начать читать адреса, пока вы не нажмете плохого парня или не достигнете алфавитного порядка сортировки и не сможете прекратить чтение.
Если у вас есть больше доменов, знайте, как вы можете стать еще умнее. Поскольку вы знаете, что количество действительных отправителей для компании довольно ограничено, вы можете создать гораздо меньший проверенный белый список действительных отправителей. Если отправитель находится в белом списке, вы можете пропустить другие проверки уже.