What.NET коллекция обеспечивает самый быстрый поиск


у меня есть 60K элементов, которые должны быть проверены против списка поиска 20k. Есть ли объект коллекции (например List,HashTable), что обеспечивает исключительно быстрый Contains() способ? Или мне придется написать свою собственную? В других словах, по умолчанию Contains() метод просто сканировать каждый элемент или он использует лучший алгоритм поиска.

foreach (Record item in LargeCollection)
{
    if (LookupCollection.Contains(item.Key))
    {
       // Do something
    }
}

Примечание. Список поиска уже отсортирован.

8 124

8 ответов:

в самом общем случае, рассмотрим System.Collections.Generic.HashSet как ваш по умолчанию "содержит" структуру данных рабочей лошади, потому что это занимает постоянное время для оценки Contains.

фактический ответ на вопрос "Что такое самая быстрая поисковая коллекция" зависит от вашего конкретного размера данных, упорядоченности, стоимости хэширования и частоты поиска.

Если вам не нужен заказ, попробовать HashSet<Record> (новый для .Net 3.5)

Если вы это сделаете, используйте List<Record> и звонок BinarySearch.

вы рассматривали List.BinarySearch(item)?

Вы сказали, что ваша большая коллекция уже отсортирована, так что это кажется идеальной возможностью? Хэш, безусловно, будет самым быстрым, но это вызывает свои собственные проблемы и требует гораздо больше накладных расходов для хранения.

следует читать этот блог эта скорость проверила несколько различных типов коллекций и методов для каждого, используя как однопоточные, так и многопоточные методы.

согласно результатам, BinarySearch в списке и SortedList были лучшими исполнителями, постоянно бегущими шея в шею, когда они искали что-то как "ценность".

при использовании коллекции, что позволяет "ключи", словарь, ConcurrentDictionary, HashSet и хеш-таблицы выполняется лучший в целом.

держите оба списка x и y в отсортированном порядке.

Если X = Y, выполните действия, если X

время выполнения этого пересечения пропорционально мин (размер (x), размер (y))

не выполнить a .Содержит () цикл, это пропорционально x * y, что намного хуже.

Если вы можете сортировать свои элементы, то есть гораздо более быстрый способ сделать это, а затем выполнять поиск ключей в хэш-таблице или b-дереве. Хотя, если вы предметы не сортируются, вы все равно не можете поместить их в b-дерево.

в любом случае, если сортируемый сортировать оба списка, то это просто вопрос ходьбы список поиска в порядке.

Walk lookup list
   While items in check list <= lookup list item
     if check list item = lookup list item do something
   Move to next lookup list item

Если вы не беспокоитесь о скрипе каждый последний бит производительности предложение использовать хэш-набор или двоичный поиск является твердым. Ваши наборы данных просто недостаточно велики, что это будет проблемой в 99% случаев.

но если это всего лишь один из тысяч раз, когда вы собираетесь это сделать, и производительность критична (и оказалась неприемлемой с использованием HashSet/binary search), вы, безусловно, можете написать свой собственный алгоритм, который прошелся по отсортированным спискам сравнения, как вы пошли. Каждый список будет пройден не более одного раза, и в патологических случаях это будет неплохо (как только вы пройдете этот маршрут, вы, вероятно, обнаружите, что сравнение, предполагая, что это строка или другое нецелочисленное значение, будет реальным расходом, и что оптимизация будет следующим шагом).

если вы используете .Net 3.5, вы можете сделать более чистый код, используя:

foreach (Record item in LookupCollection.Intersect(LargeCollection))
{
  //dostuff
}

у меня нет .Net 3.5 здесь, и поэтому это непроверено. Он опирается на метод расширения. Только не это LookupCollection.Intersect(LargeCollection), вероятно, не то же самое, что LargeCollection.Intersect(LookupCollection) ... последнее, вероятно, гораздо медленнее.

это предполагает, что LookupCollection является HashSet