Очень простой автоматически расширяющийся список / массив - PullRequest
0 голосов
/ 25 марта 2010

У меня есть метод, который возвращает массив объектов фиксированного типа (скажем, MyObject).

Метод создает новый пустой Stack<MyObject>. Затем он выполняет некоторую работу и помещает некоторое число MyObjects в конец Stack. Наконец, он возвращает Stack.ToArray().

Он не изменяет уже добавленные элементы или их свойства и не удаляет их. Количество добавляемых элементов будет стоить производительности. Нет необходимости сортировать / упорядочивать элементы.

Является ли Stack лучшим вариантом для использования? Или я должен переключиться на Collection или List, чтобы обеспечить лучшую производительность и / или меньшую стоимость памяти?

Ответы [ 7 ]

5 голосов
/ 25 марта 2010

Stack<T> не будет быстрее, чем List<T>.

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

3 голосов
/ 25 марта 2010

Если порядок не имеет значения и вашему методу не нужно добавлять / удалять / редактировать элементы, которые уже были обработаны, то почему бы не вернуть IEnumerable<MyObject> и просто yield каждый предмет на ходу?

Тогда ваш вызывающий код может либо использовать последовательность IEnumerable<MyObject> напрямую, либо вызвать ToArray, ToList и т. Д.

Например ...

// use the sequence directly
foreach (MyObject item in GetObjects())
{
    Console.WriteLine(item.ToString());
}

// ...

// convert to an array
MyObject[] myArray = GetObjects().ToArray();

// ...

// convert to a list
List<MyObject> myList = GetObjects().ToList();

// ...

public IEnumerable<MyObject> GetObjects()
{
     foreach (MyObject foo in GetObjectsFromSomewhereElse())
     {
         MyObject bar = DoSomeProcessing(foo);
         yield return bar;
     }
}
1 голос
/ 25 марта 2010

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

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

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

Большинство встроенных коллекций принимают начальную емкость в качестве аргумента конструктора:

var stack = new Stack<T>(200);  // Initial capacity of 200 items.
1 голос
/ 25 марта 2010

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

0 голосов
/ 25 марта 2010

Вам не нужен стек <>, если все, что вы собираетесь сделать, это добавить. Вы можете использовать List <>. Add (http://msdn.microsoft.com/en-us/library/d9hw1as6.aspx), а затем ToArray.

(Вы также захотите установить начальную емкость, как указали другие.)

0 голосов
/ 25 марта 2010

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

.стоимость памяти для копирования стека в массив, и , вам нужен только последовательный доступ к результату, тогда вы можете вернуть Stack<T> как IEnumerable<T> вместо массива и повторить его с помощью foreach.

Все это говорит, что если этот код не докажет , это проблематично с точки зрения производительности (то есть, глядя на данные из профилировщика), я бы не стал беспокоитьсяс вызовом семантики.

0 голосов
/ 25 марта 2010

Может быть, вы используете LinkedList?

Хотя LinkedLists полезны только для последовательных данных.

...