Где я могу узнать о различных типах списков .NET? - PullRequest
29 голосов
/ 13 октября 2008

Кто-нибудь знает хороший ресурс для краткого объяснения различных типов списков, доступных в C #, и когда их использование целесообразно?

Например, List, Hashtable, Словари и т. Д.

Я никогда не совсем уверен, когда я должен использовать что.

Ответы [ 10 ]

32 голосов
/ 13 октября 2008

Это не все списки, хотя они все коллекции. Вот краткое резюме.

Неуниверсальные коллекции (API в терминах object. Типы значений в штучной упаковке.

В основном это пространство имен System.Collections :

  • ArrayList : список элементов, подкрепленных массивом. Быстрый случайный доступ для чтения / записи. Быстрое добавление в хвостовую часть, , если буфер не нуждается в изменении размера.
  • Hashtable : Отображение от ключа к значению. Ключи уникальны, значения не должны быть. Использует метод GetHashCode, чтобы получить почти O (1) доступ на чтение / запись (кроме неприятных случаев, когда все элементы имеют одинаковый хэш, или требуется перестроить хранилище резервных копий). Перебор пар ключ / значение дает непредсказуемый порядок. (Ну, по сути, непредсказуемо.)
  • SortedList : Как и Hashtable, но записи всегда возвращаются в порядке сортировки по ключу. Хранится в виде списка пар ключ / значение.
  • Стек : коллекция «Последний пришел первым»
  • Очередь : коллекция «первым пришел - первым вышел»
  • Array : фиксированный размер O (1) произвольного доступа; неуниверсальный, но также имеет строго типизированные формы

Родовые коллекции. (Строго типизированный API, не будет упаковывать типы значений (при условии подходящего T).

Они в основном находятся в System.Collections.Generic пространстве имен :

  • Список : как ArrayList
  • Словарь : например, Hashtable
  • SortedList : как SortedList
  • SortedDictionary : аналогично SortedList, но хранится в виде дерева пар ключ / значение, что повышает производительность во многих ситуациях. См. Документы для более подробной информации.
  • LinkedList : двусвязный список (быстрый доступ к голове и хвосту)
  • Stack : Like Stack
  • Очередь : Как Очередь
  • ReadOnlyCollection : список лайков , но с доступом только для чтения

Возможно, наиболее важная коллекция интерфейс равен IEnumerable IEnumerable ). Это представляет последовательность элементов так же, как поток представляет последовательность байтов. Там нет произвольного доступа, просто чтение вперед. На этом основана LINQ to Objects, и почти все типы коллекций реализуют его.

6 голосов
/ 16 октября 2008

Чтобы пояснить более ранний ответ Тобсена, в C5 Generic Collection Library есть большое количество коллекций. Я опишу некоторые из них здесь:

Очередь / Stack

  • CircularQueue<T>: Этот класс обеспечивает строго функциональность очереди и стека. Кроме того, эффективный O (1) доступ к любому элементу в стеке / очереди доступен с помощью индексатора: cq[0] (где 0 - самый старый элемент, следующий за ним в очереди, последний из которых будет извлечен) .

Списки

Примечание: ArrayList и LinkedList также могут функционировать как очереди / стеки

  • ArrayList<T>: аналогично аналогу в System.Collections.Generic (SCG), List<T>, это поддерживается массивом, гарантирующим O (1) индексацию, но в худшем случае O ( n ) вставка. O ( n ), чтобы найти предмет.
  • LinkedList<T>: аналогично аналогу SCG.LinkedList<T>. Используя двусвязный список, гарантирует O (1) вставку, но наихудший * O ( n ) индексирование (на практике пропорционально расстоянию от либо голова, либо хвост списка). Также O ( n ), чтобы найти предмет. Сортировка использует стабильную сортировку слиянием.
  • HashedArrayList<T>: аналогично ArrayList<T> выше, но не допускает дублирование. Выгода, которую вы получаете взамен, заключается в том, что время на поиск предмета и его индекса сокращено до O (1).
  • HashedLinkedList<T>: аналогично LinkedList<T> выше, но не допускает дублирование. Как и раньше, время на поиск предмета сокращено до O (1), но время на поиск его индекса остается O ( n ).
  • WrappedArray<T>: довольно похоже на ArrayList<T>, это действует как обертка вокруг массива, который реализует C5.IList<T>, но выдает исключения, если делается попытка изменить коллекцию (IsFixedSize имеет значение true и Add, Remove, Insert не работают; Sort, Shuffle и Reverse работают, однако, поскольку они являются операциями на месте).

Списки также предоставляют функциональность «Просмотр», которая представляет сегмент базового списка, позволяя выполнять локальные операции. Используя шаблоны, предложенные в книге C5, операции могут выполняться с использованием представлений, которые эффективны как для массива, так и для связанных списков. Любая операция со списком может также выполняться над представлением, ограничивая их действие подмножеством базового списка.

Сортированные коллекции

  • SortedArray<T>: аналогично ArrayList<T> за исключением того, что он хранит сортировку своих элементов и не допускает дублирование. Обратите внимание, что случайные вставки и удаления в этой коллекции происходят медленно. Эта коллекция лучше всего подходит, если число элементов мало или редко изменяется, но к ним часто обращаются по индексу или значению элемента.
  • TreeSet<T>: использует красно-черную древовидную структуру для сортировки предметов. Как набор, это не позволяет дублировать. Доступ по индексу или значению элемента и вставке / удалению занимает O ( log n ).
  • TreeBag<T>: Использует красно-черное дерево, сохраняя элементы отсортированными. Как мешок, он допускает дубликаты, но не хранит дубликаты в дереве, а хранит дубликаты путем подсчета.

И TreeSet<T>, и TreeBag<T> предоставляют возможность эффективно делать «моментальные снимки» или постоянные копии дерева в O (1), позволяя выполнять итерацию по снимку при изменении базового дерева. Обратите внимание, что каждый снимок дерева добавляет снижение производительности для обновлений дерева, но эти эффекты исчезают при удалении снимка.

Хеш-коллекции

  • HashSet<T>: Коллекция, в которой для хранения используется простая хеш-таблица. Доступ по значению элемента занимает O (1). Как набор, это не позволяет дублировать. Предоставляет функцию BucketCostDistribution(), которая может помочь вам определить эффективность функции хэш-кода элементов.
  • HashBag<T>: аналогично HashSet<T>, но имеет семантику мешка, что означает, что дубликаты разрешены, но дубликаты сохраняются только путем подсчета.

Очередь приоритетов

  • IntervalHeap<T>: Предоставляет приоритетную очередь. Нахождение максимума и минимума - это операции O (1), удаление максимума, минимума, добавление и обновление - операции O ( log n ). Разрешает дубликаты, сохраняя их явно (не считая).

Словари

  • HashDictionary<H,K>: аналогично SCG.Dictionary<H,K>, обеспечивает доступ к записи, вставку и удаление в O (1). Также обеспечивает функцию BucketCostDistribution() как HashSet<T> выше. Не гарантирует какой-либо конкретный порядок перечисления.
  • TreeDictionary<H,K>: аналогично SCG.SortedDictionary<H,K>, обеспечивает постоянно отсортированный словарь с использованием красно-черного дерева. Для входа, вставки и удаления требуется O ( log n ). Гарантирует, что нумерация словаря соответствует порядку, указанному ключевым компаратором.

Охраняемые коллекции

Кроме того, C5 также предлагает «защищенные» коллекции, которые эффективно действуют как оболочка только для чтения, предотвращая изменение коллекции. Элементы в коллекции все еще могут быть изменены, но элементы не могут быть добавлены, удалены или вставлены в коллекцию.

Длинный ответ, но подробные сведения о библиотеках C5, имеющихся в вашем распоряжении. Я обнаружил, что библиотека C5 великолепна и часто использую ее в своем собственном коде, заменяя общий заголовок C # на:

using C5;
using SCG = System.Collections.Generic;
6 голосов
/ 13 октября 2008

Вы должны взять книгу об основных структурах данных. Это одна и та же теория, независимо от языка.

Краткое объяснение:

  • Array: (как, например, int[] myArray) - статический массив, который можно использовать, когда коллекция никогда не изменяется (вы не можете добавлять или удалять элементы в ней, но вы можете изменять значения отдельных элементов)
  • ArrayList: массив / список общего назначения, который позволяет относительно быстрое перечисление, а также прямой доступ. Этот список может автоматически увеличиваться при добавлении элементов, но, поскольку он хранит только Object, его редко следует использовать из-за проблем с производительностью и безопасностью типов.
  • List<T>: универсальная версия вышеуказанного ArrayList. Он обеспечивает хороший баланс между производительностью и гибкостью и должен использоваться почти всегда, когда у вас есть динамический плоский список элементов. (Новое в .NET 2.0)
  • Hashtable: работает как плоский список, но вместо того, чтобы индексировать его целыми числами, он может быть проиндексирован с использованием любого объекта. Стоит отметить, что в хеш-таблице нет «порядка».
  • Dictionary<T>: общая версия Hashtable. Используйте это в .NET 2.0 и выше вместо Hashtable по тем же причинам, что и ArrayList vs List выше.
  • Stack<T>: Предоставляет список типа «первым пришел - последним вышел». Предмет, который вы добавили последним, будет тем, который вы получите первым, когда выберете что-нибудь.
  • Queue<T>: Предоставляет список «первым пришел - первым вышел». Думайте об этом как о трубе, где вы вставляете предметы на одном конце и выбираете их на другом конце. Обычно используется для передачи сообщений, например, между резьб.

Как правило, вы должны использовать общие коллекции практически для всего, что вы делаете в .NET 2.0 и выше. Вы получите полную безопасность типов (по сравнению, например, с ArrayList и HashTable), и они намного быстрее для типов значений (целые числа, структуры, числа с плавающей точкой и т. Д.) По сравнению с неуниверсальными единицами.

Если у вас есть список элементов, который никогда не изменится, или вам не нужна / не нужна гибкость List<T>, вы, конечно, можете использовать массив, поскольку он имеет наименьшее количество служебных данных.

Рекомендация при возврате коллекции из открытого метода или свойства - привести ее к менее гибкому интерфейсу. Таким образом, если у вас есть список, который вы возвращаете, вы можете привести его к IEnumerable<int>, что означает, что ваш потребитель не может добавлять элементы в него (если, конечно, он не возвращает его, но он все еще указывает пользователям). Приведение его также даст вам гибкость для изменения базовой структуры данных позже при сохранении стабильности API. Вы также можете выбрать ICollection<int> или IList<int>, чтобы показать немного больше функциональности, но при этом скрыть фактическую структуру данных.

5 голосов
/ 13 октября 2008

Хеш-карты

  • Словарь
  • Hashtable (не универсальный)

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

Списки произвольного доступа

  • Список
  • ArrayList (неуниверсальный)

Списки произвольного доступа используются для хранения длинного списка объектов, к которым следует обращаться случайным образом (т. Е. Вы хотите получить доступ к n-му элементу за O (1) раз). Это не хорошо, если вы хотите вставить / удалить элементы в середине списка, поскольку для этого потребуется перетасовать весь список, что может занять некоторое время.

Связанные списки и аналогичные

  • LinkedList
  • Queue
  • Stack

Связанные списки хороши, если вы не хотите получать доступ к элементам посередине, так как это займет O (N) время. Замечательно, если вы хотите вставить / удалить элементы посередине, поскольку это требует только изменения нескольких указателей.

Очереди и стеки являются слегка специализированными, так как они оптимизированы для поведения FIFO и FILO («первым пришел-первым вышел» и первым пришел-первым вышел соответственно).

2 голосов
/ 13 октября 2008

В дополнение к замечательным ответам на данный момент есть еще несколько коллекций, доступных через C5 Generic Collection Library . Документация (также на их сайте) может помочь при принятии решения, что использовать в зависимости от ваших требований.

2 голосов
/ 13 октября 2008

Список можно сортировать, но не рекомендуется публично раскрывать.

Коллекция - это базовая коллекция без излишеств.

Словарь - это набор пар ключ-значение (во многом как старая хеш-таблица, но теперь общая).

KeyedCollection - это словарь, в котором ключ можно определить по значению (это реферат, поэтому вы должны наследовать его и поддерживать функцию GetKey)

ReadOnlyCollection - это специальная коллекция, содержимое которой нельзя изменить.

ArrayList и HashTable в основном устарели, начиная с .NET 2.0.

2 голосов
/ 13 октября 2008

Если вы начинаете с MSDN doco для System.Collections , вы можете перейти к отдельным типам коллекций для получения более подробной информации об этих «списках» и о том, как их использовать. Например, документ для Hashtable говорит: «Представляет коллекцию пар ключ / значение, которые организованы на основе хеш-кода ключа».

Существует также хорошее обсуждение System.Collections.Generic в Понимание универсальных .

1 голос
/ 04 мая 2009

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

0 голосов
/ 13 октября 2008

Это примеры различных типов общих структур данных . Эти структуры данных используются повсеместно в разработке программного обеспечения.

0 голосов
/ 13 октября 2008

Intellisense покажет вам краткое описание каждого, если вы просто наберете System.collections.Generic. в окне кода. Не забывайте завершающий период. О, и есть также System.Collections.ObjectModel.. Оттуда вы сможете получить больше информации обо всем, что выглядит многообещающим из MSDN.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...