Я вижу, что предлагаемые ответы сосредоточены на производительности. Статья, представленная ниже, не дает ничего нового в отношении производительности, но объясняет основные механизмы. Также обратите внимание, что он не фокусируется на трех Collection
типах, упомянутых в вопросе, но затрагивает все типы пространства имен System.Collections.Generic
.
http://geekswithblogs.net/BlackRabbitCoder/archive/2011/06/16/c.net-fundamentals-choosing-the-right-collection-class.aspx
Выдержки:
Dictionnary <>
Словарь, вероятно, наиболее часто используемый ассоциативный контейнерный класс. Словарь - это самый быстрый класс для ассоциативных поисков / вставок / удалений, поскольку использует хеш-таблицу под обложками . Поскольку ключи хешируются, тип ключа должен правильно реализовывать GetHashCode () и Equals () , соответственно, или вы должны предоставить внешний IEqualityComparer для словаря по построению. Время вставки / удаления / поиска элементов в словаре амортизируется постоянным временем - O (1) - что означает, что независимо от того, насколько большим становится словарь, время, необходимое для поиска чего-либо, остается относительно постоянным. Это очень желательно для высокоскоростных поисков. Единственным недостатком является то, что словарь по своей природе использует хеш-таблицу, неупорядочен, поэтому вы не можете легко перемещаться по элементам в словаре в порядке .
SortedDictionary <>
SortedDictionary похож на словарь в использовании, но очень отличается по реализации. SortedDictionary использует двоичное дерево под обложками для поддержания порядка элементов по ключу . В результате сортировки, тип, используемый для ключа, должен правильно реализовывать IComparable , чтобы ключи могли быть правильно отсортированы. Сортированный словарь тратит немного времени поиска на возможность поддерживать элементы в порядке, поэтому время вставки / удаления / поиска в отсортированном словаре является логарифмическим - O (log n). Вообще говоря, с логарифмическим временем вы можете удвоить размер коллекции, и для поиска элемента требуется только одно дополнительное сравнение. Используйте SortedDictionary, когда вы хотите быстрый поиск, но также хотите иметь возможность поддерживать коллекцию в порядке по ключу.
SortedList <>
SortedList - это другой отсортированный ассоциативный класс-контейнер в общих контейнерах. И снова SortedList, как и SortedDictionary, использует ключ для сортировки пар ключ-значение . Однако, в отличие от SortedDictionary, элементы в списке SortedList хранятся как отсортированный массив элементов . Это означает, что вставки и удаления являются линейными - O (n) - потому что удаление или добавление элемента может включать перемещение всех элементов вверх или вниз в списке. Время поиска, однако, равно O (log n), потому что SortedList может использовать двоичный поиск, чтобы найти любой элемент в списке по его ключу. Так почему же вы захотите это сделать? Ответ таков: если вы собираетесь загружать SortedList заранее, вставки будут выполняться медленнее, но, поскольку индексирование массива выполняется быстрее, чем следование ссылкам на объекты, поиск выполняется немного быстрее, чем SortedDictionary. Еще раз, я бы использовал это в ситуациях, когда вы хотите быстрый поиск и хотите сохранить коллекцию в порядке по ключу, и где вставки и удаления редки.
Предварительное резюме основных процедур
Обратная связь очень приветствуется, так как я уверен, что не все правильно понял.
- Все массивы имеют размер
n
.
- Несортированный массив = .Add / .Remove - O (1), но .Item (i) - O (n).
- Сортированный массив = .Add / .Remove - O (n), но
.Item (i) - O (1).
Dictionnary
Память
KeyArray(n) -> non-sorted array<pointer>
ItemArray(n) -> non-sorted array<pointer>
HashArray(n) -> sorted array<hashvalue>
Добавить
- Добавить
HashArray(n) = Key.GetHash
# O (1)
- Добавить
KeyArray(n) = PointerToKey
# O (1)
- Добавить
ItemArray(n) = PointerToItem
# O (1)
Удалить
For i = 0 to n
, найти i
, где HashArray(i) = Key.GetHash
# O (log n) (отсортированный массив)
- Удалить
HashArray(i)
# O (n) (отсортированный массив) - Удалить
KeyArray(i)
# O (1)
- Удалить
ItemArray(i)
# O (1)
Получить предмет
For i = 0 to n
, найти i
, где HashArray(i) = Key.GetHash
# O (log n) (отсортированный массив)
- Возврат
ItemArray(i)
Loop Through
For i = 0 to n
, возврат ItemArray(i)
SortedDictionary
Память
KeyArray(n) = non-sorted array<pointer>
ItemArray(n) = non-sorted array<pointer>
OrderArray(n) = sorted array<pointer>
Добавить
- Добавить
KeyArray(n) = PointerToKey
# O (1)
- Добавить
ItemArray(n) = PointerToItem
# O (1)
For i = 0 to n
, найдите i
, где KeyArray(i-1) < Key < KeyArray(i)
(используя ICompare
) # O (n)
- Добавить
OrderArray(i) = n
# O (n) (отсортированный массив)
Удалить
For i = 0 to n
, найти i
, где KeyArray(i).GetHash = Key.GetHash
# O (n)
- Удалить
KeyArray(SortArray(i))
# O (1)
- Удалить
ItemArray(SortArray(i))
# O (1)
- Удалить
OrderArray(i)
# O (n) (отсортированный массив)
Получить предмет
For i = 0 to n
, найти i
, где KeyArray(i).GetHash = Key.GetHash
# O (n)
- Возврат
ItemArray(i)
Loop Through
For i = 0 to n
, возврат ItemArray(OrderArray(i))
SortedList
Память
KeyArray(n) = sorted array<pointer>
ItemArray(n) = sorted array<pointer>
Добавить
For i = 0 to n
, найдите i
, где KeyArray(i-1) < Key < KeyArray(i)
(используя ICompare
) # O (log n)
- Добавить
KeyArray(i) = PointerToKey
# O (n)
- Добавить
ItemArray(i) = PointerToItem
# O (n)
Удалить
For i = 0 to n
, найдите i
, где KeyArray(i).GetHash = Key.GetHash
# O (log n)
- Удалить
KeyArray(i)
# O (n)
- Удалить
ItemArray(i)
# O (n)
Получить предмет
For i = 0 to n
, найти i
, где KeyArray(i).GetHash = Key.GetHash
# O (log n)
- Возврат
ItemArray(i)
Loop Through
For i = 0 to n
, возврат ItemArray(i)