2010-06-04 3 views
25

Мне было интересно, какой тип будет иметь лучшую производительность и который, по вашему мнению, должен использоваться.Что лучше использовать массив или Список <>?

Например, у меня есть список строк, не зная, сколько предметов мне понадобится, поэтому функция .Add (String) действительно удобна. Я могу легко добавлять новые строки в список в любое время.

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

Перечислены новые массивы?

+1

@Evan: Вторая часть вашего комментария крайне вводит в заблуждение. Вы можете инициализировать «Список » с определенной емкостью так же, как и с массивом. Если вы знаете размер заранее, неважно, какой из них вы используете, и если вы не знаете размер заранее **, поскольку в вопросе четко указано **, то вы действительно * не можете * использовать массив , Если у вас есть доказательства того, что массивы предлагают «намного лучшую» производительность чтения, отправьте ответ с этими доказательствами. – Aaronaught

ответ

36

Больше контекста действительно необходимо, чтобы ответить на этот вопрос правильно:

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

  • Если коллекция не должна изменяться внешним миром, используйте IEnumerable<T>.
  • Если коллекция будет изменена внешним миром, используйте ICollection<T>.
  • Если требуется индексированный доступ, используйте IList<T>.

В частной реализации, это не так важно использовать абстрактные типы:

  • Если вам нужен индексированный доступ и знать конечный размер, используйте T[] или List<T>.
  • Если вам нужен индексный доступ и не знаете конечный размер, используйте List<T>.
  • Если вы планируете получать доступ к элементам в шаблоне LIFO, используйте Stack<T>.
  • Если вы планируете получать доступ к элементам в шаблоне FIFO, используйте Queue<T>.
  • Если вам нужно получить доступ к элементам в начале и конце списка, но не посередине, используйте LinkedList<T>.
  • Если вы не хотите дублировать, используйте HashSet<T>.

В .NET 4.0 у вас есть еще несколько вариантов, но это основы.

+0

«Если коллекция не должна изменяться внешним миром, используйте IEnumerable » - я не согласен с этой характеристикой.Возвращение IEnumerable не поможет, если объект, на который ссылается возвращаемое значение, является изменчивым списком - вызывающий может всегда отбрасывать. Вы должны вернуть IEnumerable , если вызывающий абонент должен иметь возможность перечислять, ICollection , если ему также нужен счетчик, а IList , если ему потребуется индексированный доступ. В ** все ** из приведенных выше случаев, если сбор не должен быть изменен внешним миром, оберните его в сборку только для чтения (например, используя Список .AsReadOnly). – Joe

+1

@ Joe: Я не поклонник этого аргумента. Вызывающий может всегда пытаться использовать ** что-либо **, вы даете его * что-либо * еще - это просто плохой дизайн, чтобы сделать это. Вы можете обернуть все результаты в 'ReadOnlyCollection ', если хотите, но это не защитит вас от * враждебных * вызывающих; они могут просто использовать Reflection, чтобы получить во внутреннем изменяемом списке. Если это ультрабезопасный код, единственным способом гарантировать этот конкретный инвариант является возврат * new *, сгенерированный 'IEnumerable ' экземпляр, т. Е. Путем возврата 'originalEnumerable.Select (x => x) .ToArray()'. – Aaronaught

+0

Но в любом случае рекомендации взяты из перспективы обнаружения и обслуживания кода (написания самодокументирующего кода), а не с точки зрения безопасности; если вы находитесь в последнем лагере, то у вас есть много других вещей, о которых нужно беспокоиться. Это также причина, по которой я использовал фразу «не должен», а не «не должен» - это не гарантия, просто очень сильный намек. 'ReadOnlyCollection ' даст ошибку * runtime * при попытке изменения; вы захотите поймать такие ошибки в * время компиляции *, когда это возможно. – Aaronaught

22

List<String> реализован с использованием массива String[].

Если вы не знаете, сколько элементов вам придется использовать List<String>

Вы можете дать оцененный (или максимальное) количество элементов, которые вы ожидаете в параметре мощности конструктора (new List<String>(10)), это будет начальный размер базового массива.

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

Что я делаю: когда я знаю точный размер коллекции, и я знаю, что я не изменю размер коллекции, я использую массив (String[]). В противном случае я использую List<String>.

Кстати, это касается любого типа, а не только String.

+0

+1. для упоминания первоначальной емкости списка. –

+0

так же. Хорошее «реальное мировоззрение» –

+0

+1 за лучший ответ, но это только на полпути к сравнению различий. [Чтение производительности] Для массивов значение, если индекс можно сразу получить, потому что смещение является статическим, тогда как со списками элементы необходимо обходить, чтобы получить значение индекса. Для больших коллекций это может сильно повлиять на производительность. [Производительность записи] Напротив, списки могут расти неограниченно, без необходимости перемещения данных. С массивом вам нужно выделить новый массив и скопировать в него память (действительно неэффективно). Потоки памяти - это ответ на растущие массивы. –

7

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

2

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

2

Если вам нужна динамическая калибровка, перейдите по ссылке List<string>.

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

Если у вас есть коллекция в статическом размере, вы все равно можете использовать string[].

2

Конечно, это зависит от вашего приложения, но в условиях List<string> (или даже просто IEnumerable<string> предпочтительнее.

3

Использование списка <> в большинстве случаев все, и не беспокоиться о производительности. Существует хороший шанс вы пройдете всю свою карьеру и никогда не будете нуждаться в настройке производительности, преобразовывая список <> в массив.

3

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

Смежные вопросы