Das Löschen eines großen Bereichs von Elementen am Anfang von TList
ist teuer. Obwohl der Klassenname schmeichelt, um zu täuschen, ist ein TList
tatsächlich ein Array. In TList
gibt es keine Möglichkeit, einen Bereich zu löschen - jeder Eintrag muss einzeln gelöscht werden, und dann wird der Rest der Liste nach unten verschoben. Für einen großen Bereich, der eine Menge Neuzuweisungen und vollständige Listenbewegungen provozieren wird.
Wenn Sie ein moderneres Delphi hätten, könnten Sie die generische Listenklasse TList<T>
verwenden und nutzen Sie die Methode DeleteRange
. Die Dokumentation enthält diese wichtige Anmerkung:
Dies ist eine O (ACount) -Operation.
In Delphi 2006 können Sie etwas mit äquivalenten Leistungsmerkmalen wie diesem schreiben:
%Vor% Wie Marcelo bereits gesagt hat, könnten Sie den ganzen Block kopieren, aber anstatt dieses Element nach Element zu schreiben, können Sie das Ganze mit einem Aufruf zu Move () verschieben, indem Sie TList.List
als Argument verwenden.
Beachten Sie, dass TList.List
in älteren Delphi-Versionen ein PPointerList
( ^TPointerList; TPointerList = array[0..MaxListSize - 1] of Pointer;
) war und in Delphi XE2 zu TPointerList
( TPointerList = array of Pointer;
) wurde. Daher sollten Sie die korrekte Indirektion verwenden:
und
%Vor%So machen Sie das in XE2, denn TList ist ein Array von Zeigern.
Die Implementierung wird in Delphi 2006 ähnlich sein, aber ich kann den Code nicht schreiben, da ich 2006 nicht habe.
%Vor%Solange all die Dinge, auf die die Zeiger zeigen, anderswo Speicher verwaltet werden, gibt es kein Leck.
Hier ist der Beweis:
%Vor%Der Beweis weist große Speicherlecks auf, aber wir haben die Objekte nur zum Anzeigen der Werte erstellt.
Wenn die Reihenfolge wichtig ist und Sie N Elemente an der Vorderseite entfernen müssen:
%Vor%Ich habe diesen Code nicht wirklich gut durchdacht, also müssen Sie nach Fehlern und ähnlichem suchen.
Wenn Reihenfolge nicht wichtig ist, können Sie einfach die letzten N Elemente mit den ersten N Elementen austauschen und die letzten N Elemente wie oben löschen.
Hier ist ein Gedanke: Wenn Sie wissen, dass alle Elemente in Ihrer Liste zugewiesen sind, können Sie die zu entfernenden Elemente löschen und einfach TList.Pack () aufrufen, um herauszufinden, wo sich die leeren Stellen befinden und alles andere beiseite zu schieben effizient wie möglich. Dies erfordert jedoch einen Scan durch alle Elemente, also ist es möglicherweise nicht das, was Sie wollen, aber es verwendet auch nicht Löschen (und verhindert somit Notofy-Aufrufe). Die Implementierung von Pack hat sich zwischen D2006 und XE2 nicht ein wenig geändert, so dass Sie sich auf die Effizienz verlassen können.
Beachten Sie, dass Sie, um die Elemente zu entfernen, die Sie entfernen möchten, List[aIndex] := nil
verwenden könnten, aber dies würde immer noch einen Notify () -Aufruf erzwingen, also könnte List.List[aIndex] := nil
dafür schneller sein.
Verwenden Sie zunächst BeginUpdate und EndUpdate, um zu verhindern, dass die Benutzeroberfläche der TList aktualisiert wird, indem Sie jedes Element löschen.
Sekunde: Versuchen Sie, zuerst die Elemente an der untersten Stelle in der Liste zu löschen. Mit anderen Worten, das Löschen von Elementen von oben nach unten nimmt die Liste bei anderen Elementen weniger effizient.
Tags und Links delphi delphi-2006 tlist