2009-02-13 1 views
2

Большая часть моего опыта программирования - это язык, на котором есть одна структура данных коллекции - массив. Теперь, когда я работаю в основном в .NET, я пришел к пониманию огромного количества доступных мне инструментов, но мне также сложно определить, какие инструменты лучше всего подходят для каждой проблемы. Я нахожу, что это часто случается с коллекциями.System.Collections - почему так много вариантов?

Уверен, что я смогу найти подходящий инструмент для работы быстрее со временем/опытом, но может ли кто-нибудь предложить некоторые рекомендации, какие классы коллекций подходят для каких целей? Любые хорошие эмпирические правила?

EDIT: Я нахожу, что я использую List (T) почти всегда, что как бы порождает этот вопрос. Я знаю, что есть особые причины использовать другие классы. Хотя List (T) работает чаще всего, я хочу избежать помех в общий список, когда другая структура лучше подходит. Я должен уметь выявлять эти случаи.

Спасибо!

ответ

15

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

C++, например, поддерживает только массивы «коллекции» изначально («коллекции» используются здесь очень слабо), но с добавлением указателей вы можете реализовать эквивалент любой структуры данных коллекций, доступной в .Net. На самом деле, если вы посмотрите в стандартной библиотеке шаблонов C++, вы найдете реализации запасов для большинства общих структур.

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

При принятии решения о том, какой тип коллекции использовать, вы должны посмотреть, как он будет использоваться most ofen. Например, все объекты в коллекции ожидаются одного типа, унаследованные от того же типа или любого типа? Собираетесь ли вы часто добавлять и удалять элементы? Если это так, вы всегда будете нажимать/поп, элементы очереди/деактивации или вам нужно добавлять элементы в определенные места? Будете ли вы искать конкретные предметы по ключевым словам, по индексу или обоим? Если по ключу, как определяется ключ?

Некоторые из наиболее распространенных коллекций:

  • List<T>, вероятно, должны быть использованы в большинстве ситуаций, когда вы привыкли использовать массив. Он поддерживает поиск по индексу с использованием того же синтаксиса, что и массив с производительностью, приближающийся к характеристикам массива, строго типизирован и делает очень легко добавлять или удалять элементы и очень быстро добавлять или портировать элементы (вставляя их в конкретный положение намного медленнее).

  • LinkedList<T> должно звучать знакомо, если вы прошли профессиональную подготовку по информатике. Он использует синтаксис, аналогичный List, но оптимизирован по-разному: поисковые запросы медленнее, потому что они требуют перемещения по списку, в то время как добавление или удаление элемента в определенную позицию может быть намного быстрее.

  • Dictionary<TKey, TValue> использует синтаксис, аналогичный List<T>, но вместо индекса массива вы кладете ключевое значение в скобки. Словари велики, потому что поиск определенных предметов по ключевым словам считается очень быстрым, тем, что независимо от количества предметов в словаре он всегда будет занимать примерно такое же количество времени, чтобы найти тот, который вам нужен.

  • SortedList<TKey, TValue> работает много, как словарь, за исключением того, что при повторении его элементов возвращаются отсортированные по ключу. Тем не менее, вы не можете найти n-й элемент без первого повторения всех элементов перед ним.

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

  • Не забывайте, что старые standbys: Stack и Queue. Опять же, если у вас есть какое-либо официальное образование в области информатики, у вас уже должно быть довольно хорошее представление о том, как эти работы основаны на их именах.

И наконец, большинство из этих коллекций (массив включен!) Реализуют набор общих интерфейсов. Эти интерфейсы очень полезны, поскольку вы можете писать программу против интерфейса, а не для конкретной коллекции, а затем ваша функция может принимать любую коллекцию, которая реализует этот интерфейс. Например, следующий код будет работать пройдет ли вы в массив строк, а List<string>, или любой другой IEnumerable<string>:

void WriteToConsole(IEnumerable<string> items) 
{ 
    foreach (string item in items) 
    { 
     Console.WriteLine(item); 
    } 
} 

Другие интерфейсы стоит посмотреть на включают IList<T>, ICollection<T> и IQueryable<T>.

+0

Некоторые вещи, которые вы можете добавить к своему отличному ответу: добавление элементов в список происходит только быстро, если вы добавите их в конце; и упомянуть LinkedList , который имеет очень быстрые вставки и удаления в любом месте, но не поддерживает элементы индексации напрямую. – Thomas

+1

+1 краткий ответ. –

0

Такие коллекции, как Stacks, Queues, SortedList, Dictionary, HashTable, являются стандартными структурами данных, которые пригождаются в различных ситуациях.

Очередь позволяет реализовать FIFO без необходимости делать это самостоятельно. Стеки дают вам LIFO. SortedLists дает вам предварительно отсортированный список и так далее.

Есть много других в пространстве имен коллекций, и все обсуждаются here.

3

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

List<string> items = new List<string>(); 
items.Add("abc"); 
items.Add("dfg"); 

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

ArrayList items = new ArrayList(); 
items.Add("abc"); 
items.Add(1); 
items.Add(DateTime.Now); 

SortedLists и Hashtables являются магазин пар ключ-значение. вы можете определить ключ для своих предметов. это поможет вам быстро найти их. SortedLists автоматически сортируются Hastables.

Hashtable items1 = new Hashtable(); 
items1.Add("item1", "abc"); 
items1.Add("item2", "dfg"); 

SortedList items2 = new SortedList(); 
items2.Add("Second", "dfg"); 
items2.Add("First", "abc"); 

Надеюсь, это поможет!

0

Два совета, которые я могу предложить: 1. Используйте коллекцию Generic как можно больше. 2. При принятии решения между HashSet и коллекцией списка, действительно посмотрите, на что вы собираетесь их использовать. Hashsets может быть быстрее при поиске, но также замедляется со вставками (я нашел).

0

Алгоритмы и структуры данных. У каждого есть свои преимущества и недостатки, и каждый из них имеет свою цель.

0

есть много сообщений, связанных с этой проблемой, вы должны подумать, ЧТО вам действительно нужно делать. вам нужен строковый ключ (¿), как данные должны быть заполнены, вам нужен собственный метод, чтобы найти, существует ли какой-либо ключ или существует какое-либо значение (?)

Дженерики наиболее часто используются мной , но есть причина для других;)

http://discuss.fogcreek.com/dotnetquestions/default.asp?cmd=show&ixPost=5119

1

Как и многие другие вещи в компьютерной науке, когда есть несколько вариантов, как правило, означает, что есть несколько способов сделать что-то. Как говорили другие, существуют различные преимущества и недостатки каждой коллекции. Независимо от того, используете ли вы общие версии коллекций или нет, в конечном счете, все коллекции обеспечивают эти операции:

  • вставки
  • обновление
  • удалить
  • поиска
  • перечисление

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

Сравните это со списком. Список очень быстрый для вставки. Поиск занимает больше времени. Для операций обновления и удаления требуется, чтобы у вас был элемент уже и довольно быстро. Перечисление для массива и списка примерно одинаково.

Все коллекции также имеют определенное поведение, например, коллекция поддерживает сортировку. Если это так, то операции вставки/обновления/удаления будут занимать больше времени, но ускорят поиск.

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