В каком-то библиотечном коде у меня есть Список, который может содержать 50 000 или более элементов.
Вызывающие библиотеку могут вызывать методы, в результате которых строки добавляются в список. Как эффективно проверить уникальность добавляемых строк?
В настоящее время, непосредственно перед добавлением строки, я сканирую весь список и сравниваю каждую строку со строкой, которая будет добавлена. Это начинает показывать проблемы масштаба более 10000 пунктов.
Я оценим это, но заинтересован в понимании.
- если я заменим List <> на Dictionary <>, будет ли ContainsKey () заметно быстрее, когда список увеличится до 10 000 элементов и выше?
- если я отложу проверку уникальности до того, как будут добавлены все элементы, будет ли это быстрее? В этот момент мне нужно будет проверить каждый элемент на предмет соответствия каждому другому элементу, но все равно это операция n ^^ 2.
EDIT
Некоторые основные результаты тестов. Я создал абстрактный класс, который предоставляет 2 метода: Fill и Scan. Заполнить просто заполняет коллекцию с n предметов (я использовал 50000). Scan сканирует список m раз (я использовал 5000), чтобы увидеть, присутствует ли данное значение. Затем я построил реализацию этого класса для List, а другой для HashSet.
Используемые строки имели одинаковую длину 11 символов и генерировались случайным образом с помощью метода в абстрактном классе.
Очень простой микро-тест.
Hello from Cheeso.Tests.ListTester
filling 50000 items...
scanning 5000 items...
Time to fill: 00:00:00.4428266
Time to scan: 00:00:13.0291180
Hello from Cheeso.Tests.HashSetTester
filling 50000 items...
scanning 5000 items...
Time to fill: 00:00:00.3797751
Time to scan: 00:00:00.4364431
Так, для строк такой длины HashSet примерно в 25 раз быстрее, чем List, при сканировании на уникальность. Кроме того, для этого размера коллекции HashSet имеет нулевое наказание по сравнению со списком при добавлении элементов в коллекцию.
Результаты интересны и не действительны. Чтобы получить достоверные результаты, мне нужно было бы сделать интервалы прогрева, многократные испытания со случайным выбором реализации. Но я уверен, что это немного сдвинет планку.
Спасибо всем.
EDIT2
После добавления рандомизации и множественных испытаний HashSet стабильно превосходит List в этом случае примерно в 20 раз.
Эти результаты не обязательно верны для строк переменной длины, более сложных объектов или разных размеров коллекции.