Какие знаете коллекции?csharp-34

Основные категории коллекций

1. Простые коллекции

List<T>        // Динамический массив
LinkedList<T>  // Двусвязный список
Queue<T>       // Очередь (FIFO)
Stack<T>       // Стек (LIFO)

2. Коллекции с ключами

Dictionary<TKey, TValue>  // Хэш-таблица
SortedDictionary<TKey, TValue>  // На основе бинарного дерева
Hashtable                 // Устаревший non-generic аналог Dictionary

3. Множества

HashSet<T>       // Неупорядоченное множество уникальных элементов
SortedSet<T>     // Упорядоченное множество

4. Специализированные коллекции

ObservableCollection<T>  // Для WPF/Silverlight (уведомляет об изменениях)
ConcurrentBag<T>         // Потокобезопасная коллекция
BlockingCollection<T>    // Для Producer-Consumer сценариев

Подробный разбор основных коллекций

List - динамический массив

var list = new List<int> {1, 2, 3};
list.Add(4);             // O(1) амортизированное
list.Insert(0, 0);       // O(n)
int val = list[2];       // O(1)

Применение: Основная "рабочая лошадка" для хранения элементов, когда нужен доступ по индексу.

LinkedList - связный список

var linkedList = new LinkedList<string>();
linkedList.AddLast("first");  // O(1)
linkedList.AddFirst("zero");  // O(1)

Применение: Когда важны частые вставки/удаления в середине коллекции (O(1) при наличии ссылки на узел).

Dictionary<TKey, TValue> - хэш-таблица

var dict = new Dictionary<string, int>();
dict["one"] = 1;        // O(1)
dict.ContainsKey("two"); // O(1)

Применение: Быстрый поиск по ключу, ассоциативные массивы.

HashSet - множество

var set = new HashSet<int>();
set.Add(1);             // O(1)
set.UnionWith(new[] {2, 3}); // Объединение множеств

Применение: Проверка уникальности, математические операции над множествами.

Queue - очередь

var queue = new Queue<string>();
queue.Enqueue("first"); // O(1)
string item = queue.Dequeue(); // O(1)

Применение: Обработка задач в порядке поступления (FIFO).

Stack - стек

var stack = new Stack<double>();
stack.Push(3.14);      // O(1)
double val = stack.Pop(); // O(1)

Применение: Алгоритмы с LIFO логикой (например, отмена действий).

Потокобезопасные коллекции

ConcurrentDictionary<TKey, TValue>  // Потокобезопасный словарь
ConcurrentQueue<T>                  // Потокобезопасная очередь
ConcurrentStack<T>                  // Потокобезопасный стек
ConcurrentBag<T>                    // Неупорядоченная коллекция

Устаревшие non-generic коллекции

ArrayList       // Устаревший аналог List<T>
Hashtable       // Устаревший аналог Dictionary<TKey, TValue>
Queue           // Устаревший аналог Queue<T>

Сравнение производительности операций

КоллекцияДобавлениеПоискУдалениеДоступ по индексу
List<T>O(1)*O(n)O(n)O(1)
LinkedList<T>O(1)O(n)O(1)**O(n)
Dictionary<K,V>O(1)O(1)O(1)-
HashSet<T>O(1)O(1)O(1)-
Queue<T>O(1)-O(1)-
Stack<T>O(1)-O(1)-

*Амортизированная сложность для List.Add() **O(1) при наличии ссылки на узел

Выбор коллекции по сценарию использования

  1. Частый доступ по индексу → List
  2. Частые вставки/удаления в середине → LinkedList
  3. Быстрый поиск по ключу → Dictionary<K,V>
  4. Уникальные элементы → HashSet
  5. Порядок FIFO → Queue
  6. Порядок LIFO → Stack
  7. Многопоточность → Concurrent-коллекции

Резюмируем:


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