Ich folgte Tim Williams Ratschlag und führte einige Geschwindigkeitstests durch.
Für jede Art von Sammlung/Array, fügte ich zuerst 100.000 Objekte der Klasse "SpeedTester" hinzu, die einfach ein Shell-Objekt war, das eine Long-Variable (mit get/set-Eigenschaften) enthielt. Der Wert der Variable war der Wert des Schleifenindexes (zwischen 1 und 100.000).
Dann machte ich eine zweite Schleife, bei der auf jedes Objekt in der Sammlung/im Array zugegriffen und der lange Eigenschaftswert des Objekts einer neuen Variablen zugewiesen wurde vom Typ lang. Ich machte 3 Runden pro Methode und gemittelt die Zeiten für die Und-Schleifen.
Die Ergebnisse sind wie folgt:
Method Avg Add Time Avg Get Time Total Time
Collection Indexed 0.305 25.498 25.803
Collection Mapped 1.021 0.320 1.342
Collection Indexed For Each 0.334 0.033 0.367
Collection Mapped For Each 1.084 0.039 1.123
Dynamic Array Typed 0.303 0.039 0.342
Static Array Typed 0.251 0.016 0.266
Die Methoden Sammlung indexiert und Sammlung Mapped beteiligt, die Objekte in einer Sammlung zu halten. Die erste wurde ohne Schlüssel hinzugefügt, die zweite wurde mit einem Schlüssel hinzugefügt, bei dem es sich um die lange Eigenschaft des Objekts handelte, die in eine Zeichenfolge konvertiert wurde. Auf diese Objekte wurde dann in einer for-Schleife mit einem Index von 1 bis c zugegriffen. Die nächsten beiden Methoden waren identisch mit den ersten beiden in der Art und Weise, wie Variablen zur Sammlung hinzugefügt wurden. Für die Get-Schleife habe ich jedoch anstelle einer for-Schleife mit einem Index eine for-each-Schleife verwendet.
Das angegebene dynamische Array war eine benutzerdefinierte Klasse, die ein Array vom Typ SpeedTester enthielt. Jedes Mal, wenn eine Variable hinzugefügt wird, wurde die Größe des Arrays um 1 Slot erweitert (mit ReDim Preserve). Die Get-Schleife war eine For-Schleife mit einem Index von 1 bis 100.000, wie es für ein Array typisch ist.
Schließlich war das typisierte statische Array einfach ein Array vom Typ SpeedTester, der mit 100.000 Slots initialisiert wurde. Offensichtlich ist dies die schnellste Methode. Seltsamerweise lag ein Großteil seiner Geschwindigkeitsgewinne eher in "Getting" als "Adding".Ich hätte angenommen, dass das Hinzufügen für die anderen Methoden aufgrund der Notwendigkeit der Größenänderung langsamer wäre, während das Holen jedes Objekts nicht schneller als ein dynamisches Array wäre.
Ich war erstaunt über den Unterschied zwischen der Verwendung einer for-Schleife und einer for-each-Schleife für den Zugriff auf Objekte einer indizierten Sammlung. Ich war auch überrascht von der Schlüssel-Lookup-Geschwindigkeit der gemappten Sammlung - viel, viel schneller als die Indizierung und vergleichbar mit allen anderen Methoden außer dem statischen Array.
Kurz gesagt, sie sind alle brauchbare Alternativen für mein Projekt (mit Ausnahme der ersten und letzten Methoden, zuerst wegen seiner Langsamkeit, zuletzt, weil ich dynamisch veränderbare Arrays brauche). Ich weiß absolut nichts darüber, wie die Sammlungen tatsächlich implementiert werden, oder die Implementierungsunterschiede zwischen einem dynamischen und einem statischen Array. Jede weitere Einsicht würde sehr geschätzt werden.
EDIT: Der Code für den Test selbst (das dynamische Array)
Public Sub TestSpeed()
Dim ts As Double
ts = Timer()
Dim c As TesterList
Set c = New TesterList
Dim aTester As SpeedTester
Dim i As Long
For i = 1 To 100000
Set aTester = New SpeedTester
aTester.Number = i
Call c.Add(aTester)
Next i
Dim taa As Double
taa = Timer()
For i = c.FirstIndex To c.LastIndex
Set aTester = c.Item(i)
Dim n As Long
n = aTester.Number
Next i
Dim tag As Double
tag = Timer()
MsgBox "Time to add: " & (taa - ts) & vbNewLine & "Time to get: " & (tag - taa)
End Sub
Und für die dynamische Array-Klasse TesterList:
Private fTesters() As SpeedTester
Public Property Get FirstIndex() As Long
On Error GoTo Leave
FirstIndex = LBound(fTesters)
Leave:
On Error GoTo 0
End Property
Public Property Get LastIndex() As Long
On Error GoTo Leave
LastIndex = UBound(fTesters)
Leave:
On Error GoTo 0
End Property
Public Sub Add(pTester As SpeedTester)
On Error Resume Next
ReDim Preserve fTesters(1 To UBound(fTesters) + 1) As SpeedTester
If Err.Number <> 0 Then
ReDim fTesters(1 To 1) As SpeedTester
End If
Set fTesters(UBound(fTesters)) = pTester
On Error GoTo 0
End Sub
Public Function Item(i As Long) As SpeedTester
On Error GoTo Leave
Set Item = fTesters(i)
Leave:
On Error GoTo 0
End Function
Und schließlich, die sehr einfache SpeedTester Objektklasse :
Private fNumber As Long
Public Property Get Number() As Long
Number = fNumber
End Property
Public Property Let Number(pNumber As Long)
fNumber = pNumber
End Property
Wie oft ändern Sie die Größe? VBA ermöglicht die dynamische Größenanpassung von Arrays über 'redim preserve', wenn dies nicht oft vorkommt und/oder Sie die Größe des neuen Arrays kennen und Sie ein Array (statt einer Sammlung) weiter verwenden können. – enderland
Ob Differenzen signifikant sind, hängt wahrscheinlich von Ihrem genauen Anwendungsfall ab. Sieht so aus, als wäre es sehr einfach zu testen: Hast du irgendwelche Vergleiche gemacht? –