2011-12-15 4 views
1

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

Что такое эффективный способ сделать это?

Предположим, что объекты довольно просты и могут быть созданы быстро с конструктором без параметров по умолчанию. Что-то вроде этого:

class MyObject 
{ 
    private int a; 

    public int A 
    { 
     get { return a; } 
     set { a = value; } 
    } 
} 

Конечно, я могу создать свою коллекцию, как это:

List<MyObject> list = new List<MyObject>(knownNumberOfItems); 
for (int i = 0; i < knownNumberOfItems; i++) 
    list.Add(new MyObject()); 

Но, может быть, есть лучший способ сделать то же самое?

Резюме от обсуждения:

  • Там нет более быстрого способа сделать это для ссылочных типов. Вы можете получить некоторые улучшения производительности, используя типы значений.
  • Попробуйте выделить больше места изначально, чтобы уменьшить количество перераспределений при добавлении новых элементов позже.
+0

Если это соответствует требованиям, рассмотрите возможность создания MyObject структуры. Это сбрит некоторые накладные расходы – Polity

+0

Just FYI, List подкрепляется массивом. Вы заявили, что не хотите использовать массив из-за проблем с производительностью. Использование списка вместо массива не облегчит эту проблему, потому что в списке будет использоваться массив под капотом. – Dejas

+0

@Dejas Я думаю, я ничего не могу сделать о перераспределении базового массива. Но я просто не хочу самостоятельно выполнять эти перераспределения. – Bobrovsky

ответ

2

Нет более быстрого способа, с которым я знаком. Я лично использовал фигурные скобки вокруг тела цикла for, но как способ создания списка заданного размера, заполненного отличными ссылками на новые объекты, вот и все. Важная часть состоит в том, что вы указали размер списка для начала, поэтому этим вызовам Add не потребуется перераспределять что-либо внутренне.

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

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

+0

Я думаю, что его мысль о том, что использование массивов не используется, заключается в том, что он знает, что ему нужны известные_имя_и_и_и_итем, но нужно будет добавить некоторое неизвестное количество объектов в будущем. – Dejas

+0

@Dejas: Да, но у него может быть * некоторое представление о вероятном распределении дополнительных элементов для добавления. Так, например, может быть стоит добавить дополнительные 10% в ожидании * некоторых * дополнений. –

+0

Я также использую camelCasing. Подчеркивания используются в фрагменте кода только для дополнительного акцента. – Bobrovsky

1

Не в .Net 2.0. Начиная с .Net 3.5, вы можете записать его немного короче, но скомпилированный результат будет в основном тем же.

1

Ваш путь довольно эффективен - массив создается с достаточным пространством для всех ваших предметов и list.Add невероятно быстро.

Вы испытываете проблемы с производительностью?

+0

Да, я испытываю некоторые проблемы с большими коллекциями (> 10 тысяч предметов). – Bobrovsky

+0

@ Бобровский какие проблемы, в частности? Какой код работает медленно? Вы профилировали? – phoog

+0

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

1

Я мог бы рассмотреть глядя на

LinkedList<T> list = ... 

добавить операции в связанные списки постоянное времени.

+0

Если список <> предварительно назначен (как и в его случае), добавление элемента выполняется в постоянное время, а константа меньше, чем в LinkedList. Траверса также более эффективна. Для всех практических целей он использует массив здесь. – zmbq

+1

@Dejas: Если вы знаете размер списка заранее, 'List ', инициализированный размером, является постоянным временем для операций добавления. В его примере он уже знал размер. –

+0

Благодарим вас за предложение, но мне нужно, чтобы элементы в коллекции были доступны по индексу. – Bobrovsky

1

Рассмотрите возможность создания типа типа (struct), чтобы вам не нужно выделять память для экземпляров и что ваш список не будет фрагментировать память. После этого создать список, как:

var List = new MyList<MyObject>(Enumerable<MyObject>.Repeat(new MyObject(), 
           known_number_of_items)); 

С его documentation, его гарантированно работать на O(n).это не будет работать с ссылочным типом (class), так как он будет вставлять один и тот же объект снова и снова.

+0

Благодарим вас за предложение, но в моем случае тип не может быть типом значения. – Bobrovsky

+0

@Bobrovsky: нет возможности создать непрерывное расширяемое хранилище для объектов на C#.Я предлагаю переключиться на C++, если это возможно, если это проблема производительности, потому что создание огромного количества объектов по одному будет подчеркивать управляемую память и сборщик мусора, а на C++ вы можете просто использовать один непрерывный расширяемый контейнер (std :: вектор) – Dani

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