Структуры данных .NET: ArrayList, List, HashTable, Dictionary, SortedList, SortedDictionary - скорость, память и когда использовать каждый?

.NET имеет много сложных структур данных. К сожалению, некоторые из них очень похожи, и я не всегда уверен, когда использовать один, а когда другой. Большинство моих книг на C# и Visual Basic говорят о них в определенной степени, но они никогда не вдаются в какие-либо реальные детали.

в чем разница между Array, ArrayList, List, Hashtable, Dictionary, SortedList и SortedDictionary?

какие из них перечислимы (IList -- может делать циклы "foreach")? Какие из них используют пары ключ/значение (IDict)?

Что насчет памяти? Скорость вставки? Скорость извлечения?

есть ли другие структуры данных, заслуживающие упоминания?

Я все еще ищу более подробную информацию об использовании памяти и скорости (Big-O notation).

14 ответов


С макушки моей головы:

  • Array* - представляет собой массив памяти старой школы-своего рода псевдоним для нормального type[] массив. Может перечислить. Не может расти автоматически. Я бы предположил, что очень быстрая вставка и скорость retrival.

  • ArrayList - автоматически растет массива. Добавляет больше накладных расходов. Может перечислять., вероятно, медленнее, чем обычный массив, но все же довольно быстро. Они используются много .NET

  • List - один из моих favs-может использоваться с дженериками, поэтому вы можете иметь строго типизированный массив, например List<string>. Кроме этого, действует очень похоже ArrayList

  • Hashtable - простой старый hashtable. O(1) в o (n) в худшем случае. Может перечислять свойства value и keys и делать пары key/val

  • Dictionary - то же, что и выше, только строго типизировано через дженерики, такие как Dictionary<string, string>

  • SortedList - сортированный общий список. Замедлился при вставке, так как он должен выяснить, куда положить вещи. Может перечислять., вероятно, то же самое при извлечении, поскольку ему не нужно прибегать, но удаление будет медленнее, чем простой старый список.

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

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


Если это вообще возможно, использовать дженерики. Это включает в себя:

  • список вместо ArrayList
  • словарь вместо HashTable

во-первых, все коллекции в .NET реализуют IEnumerable.

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

Итак, хотя общие коллекции, вероятно, добавляют функции, по большей части:

  • List является общей реализацией ArrayList.
  • словарь является общей реализацией Hashtable

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

SortedDictionary-это IDictionary, который сортируется на основе ключей. SortedList-это IDictionary, который сортируется на основе требуемого IComparer.

Итак, реализации IDictionary (поддерживающие KeyValuePairs) являются: * коллекция Hashtable * Словарь * SortedList * Словаре sorteddictionary

другая коллекция, которая была добавлена в .NET 3.5, - это Hashset. Это коллекция, которая поддерживает набор оперативный.

кроме того, LinkedList является стандартной реализацией связанного списка (список является списком массивов для более быстрого поиска).


вот несколько общих советов для вас:

  • можно использовать foreach для типов, реализующих IEnumerable. IList по сути IEnumberable С Count и Item (доступ к элементам с использованием нулевого индекса) свойства. IDictionary С другой стороны означает, что вы можете получить доступ к элементам любой hashable индекса.

  • Array, ArrayList и List все IList. Dictionary, SortedDictionary и Hashtable выполнить IDictionary.

  • если вы используете .NET 2.0 или выше, рекомендуется использовать универсальные аналоги указанных типов.

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

  • структуры данных .NET находятся в System.Collections пространство имен. Существуют библиотеки типов, такие как PowerCollections, которые предлагают дополнительные данные структуры.

  • чтобы получить полное представление о структурах данных, обратитесь к таким ресурсам, как среды CLR.


хорошая шпаргалка отметить сложность для структур данных, алгоритмов и т. д.


Я сочувствую вопросу - я тоже нашел (найти? выбор сбивает с толку, поэтому я решил научно посмотреть, какая структура данных является самой быстрой (я сделал тест с использованием VB, но я думаю, что C# будет одинаковым, так как оба языка делают то же самое на уровне CLR). Вы можете видеть некоторые результаты бенчмаркинга, проведенные мной здесь (также есть некоторые обсуждения того, какой тип данных лучше всего использовать в каких обстоятельствах).


.NET структуры данных:

подробнее о том, почему ArrayList и List на самом деле разные

массивы

как утверждает один пользователь, массивы являются коллекцией" старой школы " (да, массивы считаются коллекцией, но не частью System.Collections). Но, что такое" старая школа " о массивах по сравнению с другими коллекциями, я.e те, которые вы перечислили в своем названии (здесь, ArrayList и List (of T))? Давайте начнем с основ, посмотрев на Матрицы.

для начала массивы в Microsoft .NET есть "механизмы, которые позволяют обрабатывать несколько [логически связанных] элементов как одну коллекцию" (см. связанную статью). Что это значит? Массивы хранят отдельные элементы (элементы) последовательно, один за другим в памяти с начальным адресом. Используя массив, мы можем легко получить доступ к последовательно хранимым элементам, начинающимся с этого адреса.

помимо этого и вопреки программирования 101 общие концепции, массивы действительно могут быть довольно сложными:

массивы могут быть одномерными, многомерными или jadded (зубчатые массивы стоит прочитать). Сами массивы не являются динамическими: после инициализации массива n размер резервирует достаточно места для хранения n количество объектов. Количество элементов в массиве не может увеличиваться или уменьшаться. Dim _array As Int32() = New Int32(100) резервирует достаточно места в блоке памяти для массива, содержащего примитивный тип 100 Int32 объекты (в этом случае массив инициализируется как содержащий 0s). Адрес этого блока возвращается в _array.

по статье Спецификация Общего Языка (CLS) требует, чтобы все массивы были основаны на нуле. Массивы в .NET поддерживают ненулевые массивы; однако это встречается реже. В результате "общности" нулевых массивов Microsoft потратила много времени оптимизации их производительности; следовательно, один размер, массивы на основе нуля (SZs) являются "специальными"-и действительно лучшей реализацией массива (в отличие от многомерных и т. д.)- потому что СЗС имеют конкретные инструкции языка-посредника для манипулирования ими.

массивы всегда передаются по ссылке (Как адрес памяти) - важная часть головоломки массива, чтобы знать. В то время как они проверяют границы (выдадут ошибку), проверка границ также может быть отключена на массивах.

опять же, самое большое препятствие для массивов заключается в том, что они не повторно значительные. Они имеют "фиксированную" емкость. Представляем ArrayList и List (of T) в нашу историю:

ArrayList-non-generic list

на ArrayList (вместе с List(Of T) - хотя есть некоторые критические различия, здесь, объясненные позже) - возможно, лучше всего рассматривать как следующее дополнение к коллекциям (в широком смысле). ArrayList наследуется от объекта IList (потомок интерфейса 'ICollection'). Артефакты ArrayList, сами больше - требует больше накладных - чем списки.

IList позволяет реализации рассматривать ArrayLists как списки фиксированного размера (например, массивы); однако, помимо дополнительной функциональности, добавленной ArrayLists, нет никаких реальных преимуществ в использовании ArrayLists, которые являются фиксированным размером, поскольку ArrayLists (над массивами) в этом случае заметно медленнее.

из моего чтения ArrayLists не может быть зазубренным: "использование многомерные массивы как элементы... не поддерживаемый." Опять же, еще один гвоздь в гроб артефакты ArrayList. ArrayLists также не "типизированы" - это означает, что под всем ArrayList просто динамический массив объектов: Object[]. Это требует много бокса (неявного) и распаковки (явного) при реализации ArrayLists, снова добавляя к их накладным расходам.

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

List (of T): каким ArrayList стал (и надеялся стать)

разница в использовании памяти достаточно значительна, чтобы список (Int32) потреблял 56% меньше памяти, чем ArrayList содержащий тот же примитивный тип (8 МБ против 19 МБ в приведенной выше демонстрации: опять же, linked здесь)-хотя это результат, осложненный 64-разрядной машиной. Это различие действительно демонстрирует две вещи: во-первых (1), упакованный "объект" типа Int32 (ArrayList) намного больше, чем чистый примитивный тип Int32 (List); во-вторых (2), разница экспоненциальна в результате внутренней работы 64-разрядной машины.

Итак, в чем разница и что такое Список (Из T)? в MSDN определяет List(Of T) as,"... строго типизированный список объектов, к которым можно получить доступ по индексу."Важность здесь -" строго типизированный "бит: список (T) "распознает" типы и сохраняет объекты как их тип. Так,Int32 хранится в виде Int32, а не Object тип. Это устраняет проблемы, вызванные боксом и распаковкой.

MSDN указывает, что эта разница вступает в игру только при хранении примитивные типы, а не ссылочные типы. кроме того, разница действительно происходит в большом масштабе: более 500 элементов. Что более интересно, так это то, что документация MSDN гласит: "В ваших интересах использовать реализацию класса List(of T) для конкретного типа вместо использования класса ArrayList...."

по сути, List (of T) является ArrayList, но лучше. Это "общий эквивалент" ArrayList. Как и ArrayList, не гарантируется сортировка до сортировки (go рисунок.) List (of T) также имеет некоторые дополнительные функции.


Они довольно хорошо написаны в intellisense. Просто введите (предпочтительный), и вы получите список и краткое описание того, что доступно.


хеш-таблицы/словари являются O(1) производительность, это означает, что производительность не зависит от размера. Это важно знать.

EDIT: на практике средняя сложность времени для поиска Hashtable / Dictionary равна O (1).


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


важное замечание о Hashtable vs Dictionary для высокочастотной системной торговой техники: проблема безопасности потоков

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

таким образом, Hashtable остается "стандартным" выбором в этом отношении.


вообще-то, я думаю MSDN обеспечивает довольно хорошие ответы на все эти вопросы. Просто посмотрите коллекции .NET.


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


самые популярные структуры и коллекции данных C#

  • массив
  • ArrayList
  • список
  • LinkedList
  • словарь
  • поиска HashSet
  • стек
  • очереди
  • SortedList

C#.NET имеет множество различных структур данных, например, одной из наиболее распространенных является массив. Однако C# поставляется со многими другими базовыми структурами данных. Выбор правильной структуры данных для использования является частью написания хорошо структурированного и эффективная программа.

в этой статье я перейду к встроенным структурам данных C#, включая новые, которые вводятся в C#.NET 3.5. Обратите внимание, что многие из этих структур данных применяются для других языков программирования.

массив

возможно, самой простой и наиболее распространенной структурой данных является массив. Массив C# - это в основном список объектов. Ее характерной особенностью является то, что все объекты одного типа (в большинстве случаев) и есть конкретная ряд из них. Природа массива позволяет очень быстро получить доступ к элементам на основе их положения в списке (иначе известный как индекс). Массив C# определяется следующим образом:

[object type][] myArray = new [object type][number of elements]

примеры:

 int[] myIntArray = new int[5];
 int[] myIntArray2 = { 0, 1, 2, 3, 4 };

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

ArrayList

структура данных C#, ArrayList, является динамическим массивом. Это означает, что ArrayList может иметь любое количество объектов и любого типа. Эта структура данных была разработана для упрощения процесса добавления новых элементов в массив. Под капотом ArrayList-это массив чей размер удваивается каждый раз, когда заканчивается пространство. Удвоение размера внутреннего массива - очень эффективная стратегия, которая уменьшает количество копирования элементов в долгосрочной перспективе. Мы не будем вдаваться в доказательства этого здесь. Структура данных очень проста в использовании:

    ArrayList myArrayList = new ArrayList();
    myArrayList.Add(56);
    myArrayList.Add("String");
    myArrayList.Add(new Form());

недостатком структуры данных ArrayList является то, что необходимо вернуть возвращенные значения в их исходный тип:

int arrayListValue = (int)myArrayList[0]

источники и более подробную информацию вы можете найти здесь :