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

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

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

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

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

Стоит ли упомянуть какие-либо другие структуры данных?

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

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

user1228 24.09.2008 21:55

Я думал о том, чтобы разбить это на части, но понял, что кто-то, вероятно, сможет объединить все эти ответы в одном месте. Фактически, если кто-то сможет составить таблицу, профилирующую все, она может стать прекрасным ресурсом на этом сайте.

Pretzel 28.09.2008 19:25

Можно ли превратить этот вопрос в вики?

BozoJoe 02.03.2011 00:08

Райан, статьям по этой ссылке 14 лет (12 на момент публикации). Примечание. Я сам читаю их последнюю неделю. но они также не включают более новые технологии и отчаянно нуждаются в обновлении. И другие показатели и примеры производительности.

htm11h 17.05.2017 20:53

Есть ли место для LinkedList в вашем вопросе? Просто спрашиваю.

Kurkula 13.08.2017 21:45

@Dracolyte Я считаю, что это то, что вы хотели задать, и он был удален.

Hogan 03.03.2021 20:25
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
216
6
159 233
12
Перейти к ответу Данный вопрос помечен как решенный

Ответы 12

По возможности используйте дженерики. Сюда входят:

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

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

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

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

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

  • Список - это общая реализация ArrayList.
  • Словарь - это общая реализация Hashtable

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

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

Итак, реализации IDictionary (поддерживающие KeyValuePairs): * Хеш-таблица * Словарь * SortedList * SortedDictionary

Еще одна коллекция, добавленная в .NET 3.5, - это Hashset. Это коллекция, которая поддерживает операции над наборами.

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

Ответ принят как подходящий

С верхней части моей головы:

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

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

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

  • Hashtable - старая обычная хеш-таблица. От O (1) до O (n) в худшем случае. Может перечислять свойства значений и ключей, а также создавать пары ключ / значение

  • Dictionary - то же, что и выше, только строго типизированный с помощью универсальных шаблонов, таких как Dictionary<string, string>

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

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

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

Хеш-таблица - O (1), в худшем случае (с коллизиями) может быть O (n)

Justin Bozonier 18.10.2008 20:00

Есть много других структур данных, которые вам нужно добавить сюда. как LinkedList, Список пропуска, Стек, Очередь, Куча, Деревья, Графы. Это также очень важные структуры данных.

DarthVader 25.08.2011 23:00

ConcurrentDictionary, добавленный в .Net 4.0, предоставляет общий словарь с безопасностью потоков

Harindaka 21.12.2012 20:34

Также BlockingCollection <T> предоставляет поточно-безопасную реализацию производителя / потребителя.

Harindaka 21.12.2012 20:36

ArrayList использует виртуальные методы, а List<T> - нет. ArrayList был в значительной степени заменен на List<T> для стандартных коллекций и Collection<T> в качестве базового класса для пользовательских коллекций. Hashtable был в значительной степени заменен на Dictionary<TKey, TValue>. Я бы рекомендовал избегать ArrayList и Hashtable для нового кода.

Sam Harwell 23.05.2013 09:37

@ 280Z28 - Тебе действительно стоит написать новый ответ - Сэм был великолепен, но на данный момент ему 5 лет.

Hogan 18.06.2013 19:07

Эффективность хеш-таблиц амортизируется за O (1), а не за O (1). Подробнее здесь

RBT 21.03.2017 12:07

Вот несколько общих советов:

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

  • Array, ArrayList и List реализуют IList. Dictionary, SortedDictionary и Hashtable реализуют IDictionary.

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

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

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

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

из msdn, похоже, что sortedList реализует IDictionnary, а не IList

Haim Bendanan 23.11.2016 21:45

Зафиксированный. Спасибо за комментарий. Похоже, что SortedList хранит список ключей / значений, поэтому он в основном представляет данные словаря. Не помню, как работал этот класс, когда я впервые написал ответ ...

blackwing 05.12.2016 06:18

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

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

Не существует такого понятия, как «производительность». Сложность зависит от операции. Например, если вы вставите n элементов в Dictionary <>, это не будет O (1) из-за повторного хеширования.

Ilya Ryzhenkov 25.09.2008 01:07

К вашему сведению, даже с перефразированием Dictionary по-прежнему O (1). Рассмотрим сценарий непосредственно перед расширением словаря. Половина элементов - те, которые были добавлены с момента последнего расширения - будут хешированы один раз. Половина остатка будет дважды хэширована. Половина остатка от этого, три раза и т. д. Среднее количество операций хеширования, выполняемых для каждого элемента, будет 1 + 1/2 + 1/4 + 1/8 ... = 2. Ситуация сразу после раскрытия практически такая же, но каждый элемент был хеширован один дополнительный раз (так что среднее количество хешей равно трем). Все остальные сценарии находятся между ними.

supercat 12.03.2011 01:24

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

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

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

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

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

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

Bryan Menard 28.08.2011 02:05

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

Rob 28.08.2011 08:15

.NET 4.0 предоставляет ConcurrentDictionary <TKey, TValue>

Rob 28.08.2011 08:17

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

Самые популярные структуры и коллекции данных 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 };

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

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]

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

Я нашел раздел «Выбрать коллекцию» на странице документов Microsoft на странице «Коллекция и структура данных» действительно полезным.

Коллекции и структуры данных C#: выберите коллекцию

А также следующая матрица для сравнения некоторых других функций

Другие вопросы по теме