Следует ли обновлять элемент в List <T>по индексу быстрее, чем при использовании индекса ArrayList? - PullRequest
1 голос
/ 12 октября 2009

Я прошёл несколько тестов по использованию ArrayLists и List.

Скорость очень важна для моего приложения.

Я протестировал создание 10000 записей в каждой, нахождение элемента по индексу и затем обновление этого объекта, например:

List[i] = newX;

Использование arraylist кажется намного быстрее. Это правильно?

ОБНОВЛЕНИЕ:

Используя подход List [i], для моего подхода List<T> я использую LINQ, чтобы найти индекс, например / /

....

int index = base.FindIndex(x=>x.AlpaNumericString = "PopItem");
base[index] = UpdatedItem;

Это определенно медленнее, чем

ArrayList.IndexOf("PopItem"))
base[index] = UpdatedItem;

Ответы [ 5 ]

2 голосов
/ 12 октября 2009

Общий список (List<T>) всегда должен быть быстрее, чем ArrayList.

Во-первых, ArrayList не является строго типизированным и принимает типы object, поэтому, если вы храните типы значений в ArrayList, они будут в штучной упаковке и распакованы каждый раз, когда они добавляются или доступны.

Общий список может быть определен так, чтобы принимать только (скажем) int, поэтому при добавлении / доступе к элементам списка не нужно выполнять упаковку или распаковку.

Если вы имеете дело с ссылочными типами, вам, вероятно, все-таки лучше использовать универсальный список вместо ArrayList, поскольку, хотя в нем нет никаких операций по упаковке / распаковке, ваш общий список является безопасным для типов и не будет неявные (или явные) приведения, необходимые при извлечении вашего строго типизированного объекта из «коллекции» ArrayList типов object.

Могут быть некоторые крайние случаи, когда ArrayList работает быстрее, чем Generic List, однако я (лично) еще не сталкивался с ним. Даже документация MSDN гласит:

Вопросы производительности

При принятии решения использовать ли List <(Of <(T>)>) или класс ArrayList, оба из которых имеют похожие функциональность, помните, что Класс List <(Of <(T>)>) работает лучше в большинстве случаев и является безопасным типом. Если ссылочный тип используется для типа T из список <(Of <(T>)>), Поведение двух классов идентичны. Однако, если тип значения используется для типа T, вам необходимо учитывать вопросы реализации и бокса.

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

Убедитесь, что тип значения используется для Тип T реализует IEquatable <(Of <(T>)>) универсальный интерфейс. Если не, методы типа Contains должны вызывать Object .. ::. Equals (Object) метод, какие блоки затрагивает элемент списка. Если тип значения реализует IComparable интерфейс, и вы владеете исходный код, также реализовать IComparable <(Of <(T>)>) универсальный интерфейс для предотвращения BinarySearch и сортировать методы из боксерского списка элементы. Если вы не являетесь владельцем источника код, передайте IComparer <(Of <(T>)>) объект BinarySearch и сортировка методы

Более того, мне особенно нравится самый последний раздел этого абзаца, в котором говорится:

В ваших интересах использовать реализацию класса List <(Of <(T>)>) для конкретного типа вместо использования класса ArrayList или написания строго типизированной коллекции-оболочки самостоятельно. Причина в том, что ваша реализация должна делать то, что уже делает для вас .NET Framework, и общеязыковая среда выполнения может совместно использовать код и метаданные промежуточного языка Microsoft, чего ваша реализация не может.

Туш! :)

1 голос
/ 12 октября 2009

Исходя из вашего недавнего редактирования, кажется, что вы не проводите здесь сравнение 1: 1. В списке у вас есть объект класса, и вы ищете индекс, основанный на свойстве, тогда как в ArrayList вы просто храните значения этого свойства. Если это так, то это совершенно ошибочное сравнение.

Для сравнения 1: 1 вы должны добавить значения только в список, а не в класс. Или вы бы добавили элементы класса в ArrayList. Первый позволит вам использовать IndexOf в обеих коллекциях. Последнее повлечет за собой цикл по всему списку ArrayList и сравнение каждого элемента до тех пор, пока не будет найдено совпадение (и вы могли бы сделать то же самое для списка), или переопределение object.Equals, поскольку ArrayList использует это для сравнения.

Для интересного прочтения предлагаю взглянуть на пост Рико Мариани: Тест производительности # 7 - Улучшения в области общих характеристик и затраты - Решение . Даже в этом посте Рико также подчеркивает необходимость сравнения различных сценариев. О ArrayLists не выдается никакого общего заявления, хотя общий консенсус заключается в использовании общих списков для повышения производительности, безопасности типов и наличия строго типизированной коллекции.

Другая связанная статья: Почему я должен использовать List, а не ArrayList .

1 голос
/ 12 октября 2009

Я бы ожидал, что они будут примерно одинаковыми, если они являются типами значений. Для ArrayList есть дополнительная проверка типов / типов, но ничего особенного. Конечно, List<T> должно быть предпочтительным . Если скорость является основной проблемой (а это почти всегда не так, по крайней мере, не в этом смысле), то вам также может потребоваться профилировать массив (T[]) - сложнее (= дороже) добавлять / удалять Конечно, но если вы просто запрашиваете / присваиваете по индексу, он должен быть самым быстрым. Мне приходилось прибегать к массивам для некоторых очень локализованных критичных к производительности работ, но в 99,95% случаев это излишне, и их следует избегать.

Например, для любого из 3-х подходов (List<T> / ArrayList / T[]) я бы ожидал, что стоимость уступки будет незначительной по сравнению со стоимостью new до новый экземпляр для помещения в хранилище.

1 голос
/ 12 октября 2009

ArrayList кажется быстрее? Согласно документации (http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx) список должен быть быстрее при использовании типа значения и такой же скорости при использовании ссылочного типа. ArrayList работает медленнее с типами значений, потому что он должен блокировать / распаковывать значения при обращении к ним.

0 голосов
/ 12 октября 2009

Марк Гравелл затронул этот вопрос в своем ответе - я думаю, что это нужно подчеркнуть.

Обычно преждевременная оптимизация вашего кода - пустая трата времени!

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

Часто вы обнаружите, что это "достаточно быстро". (Это помогает начать с четкого определения «достаточно быстро» - например, «Должен быть в состоянии найти один CD в коллекции из 10000 CD за 3 секунды или меньше»)

Если это не так, поместите на него профилировщик. Почти всегда, горлышко бутылки НЕ будет там, где вы ожидаете.

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

...