четверг, 30 июня 2011 г.

Работа с TList (Delphi)

Класс TList - один из наиболее часто используемых классов в Delphi.
Данный класс реализует методы работы с массивом указателей:
  • Добавление и удаление элементов списка
  • Манипуляции над элементами списка (перестановка, сдвиг, сортировка) 
  • Поиск по списку 
Как оптимальнее использовать данный класс в работе рассмотрим подробнее...


Первое о чем хотелось сказать это, конечно, наполнение списка.
Для добавления элемента в список класс TList предусматривает метод Add. При этом если выделенной под список памяти не хватает она выделяется автоматически. Чаще всего списки наполняются в циклах с известным числом итераций. Для того, чтобы быстрее занести данные в список рекомендуется предварительно установить свойство Capacity списка равным числу добавляемых элементов. Это приведет к тому, что для списка один раз будет выделена память необходимая для всех добавляемых элементов. Данный подход позволяет работать с памятью оптимальнее. Если не устанавливать свойство Capacity то при добавлении первых двенадцати элементов список будет расширен 3 раза (по 4 элемента), при добавлении элементов до 76го еще 4 раза (по 16 элементов) далее будет расширяться на четверть текущего размера при необходимости увеличения списка. При этом если блок нового размера не будет вписываться в свободные блоки памяти на месте, весь список будет скопирован в новый блок памяти, что может сказаться на производительности. Второе преимущество данного подхода в том, что если в системе недостаточно памяти можно сразу при установке свойства Capacity получить ошибку EOutOfMemory. Что позволит тратить меньше времени на удаление созданных до ошибки элементов. Так что на заметку:
List.Clear;
List.Capacity := Count;
for I := 1 to Count do List.Add(...);

Второй момент это чтение данных.
В большинстве класс TList используется для хранения списка указателей на объекты. Для этого наследуются от данного класса или делегируют списочные свойства приватному полю этого класса. При этом часто публикуют индексное свойство для получения элемента по индексу преобразовывая его в необходимый класс. Такое архитектурное решение при последовательном чтении элементов в цикле дает лишние затраты процессорного времени. Рекомендуется при последовательном чтении в цикле обращаться напрямую к публичному свойству List класса TList. На заметку:
for I := 0 to Count - 1 do
CurrentItem := TMyClass(List.List^[I]);
Таким образом мы снимаем лишние затраты на вызов функции Get с встроенной проверкой на выход за границы массива и в случае наследования класса(ов) на лишние вызовы inherited Get(Index).

До связи =)

Комментариев нет:

Отправить комментарий