Tôi đã làm theo lời khuyên của Tim Williams và đã thực hiện một số kiểm tra tốc độ.
Đối với mỗi loại bộ sưu tập/mảng, lần đầu tiên tôi thêm 100.000 đối tượng của lớp "SpeedTester", đơn giản chỉ là đối tượng vỏ chứa một biến dài (với thuộc tính get/set). Giá trị của biến là giá trị của chỉ số vòng lặp (từ 1 đến 100.000)
Sau đó, tôi đã thực hiện vòng lặp thứ hai liên quan đến từng đối tượng trong bộ sưu tập/mảng và gán giá trị thuộc tính dài của đối tượng cho biến mới loại dài. Tôi thực hiện 3 vòng cho mỗi phương pháp, và tính trung bình thời gian cho And và nhận được vòng lặp.
Kết quả như sau:
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
Các phương pháp sưu tập được lập chỉ mục và Bộ sưu tập ánh xạ tham gia giữ các đối tượng trong một bộ sưu tập. Đầu tiên được thêm vào không có khóa, phần thứ hai được thêm vào với một khóa là thuộc tính dài của đối tượng được chuyển đổi thành một chuỗi. Các đối tượng này sau đó được truy cập trong một vòng lặp bằng cách sử dụng một chỉ mục từ 1 đến c.Count
Hai phương thức tiếp theo giống hệt với hai phương thức đầu tiên được thêm vào bộ sưu tập. Tuy nhiên, đối với vòng lặp Get, thay vì sử dụng vòng lặp for có chỉ mục, tôi đã sử dụng vòng lặp for-each.
Nhập mảng động là một lớp tùy chỉnh có chứa một mảng kiểu SpeedTester. Mỗi lần một biến được thêm vào, kích thước của mảng được mở rộng thêm 1 khe (sử dụng ReDim Preserve). Vòng lặp get là một for-loop sử dụng một chỉ mục từ 1 đến 100.000, như là điển hình cho một mảng.
Cuối cùng, mảng tĩnh được nhập chỉ đơn giản là một mảng kiểu SpeedTester, được khởi tạo với 100.000 vị trí. Rõ ràng đây là phương pháp nhanh nhất. Thật kỳ lạ, phần lớn tốc độ tăng của nó là ở Bắt hơn là Thêm.Tôi đã giả định rằng việc thêm sẽ chậm hơn đối với các phương thức khác, do nhu cầu thay đổi kích thước, trong khi việc Bắt từng đối tượng sẽ không nhanh hơn một mảng động.
Tôi đã kinh ngạc bởi sự khác biệt giữa việc sử dụng vòng lặp for-loop và for-each để truy cập các đối tượng của bộ sưu tập được lập chỉ mục. Tôi cũng ngạc nhiên bởi tốc độ tra cứu chính của bộ sưu tập được ánh xạ - nhiều, nhanh hơn nhiều so với lập chỉ mục và so sánh với tất cả các phương thức khác ngoại trừ mảng tĩnh.
Tóm lại, chúng là tất cả các lựa chọn thay thế khả thi cho dự án của tôi (trừ phương pháp thứ nhất và cuối cùng, trước hết vì chậm trễ, cuối cùng vì tôi cần mảng có thể thay đổi kích thước động). Tôi biết hoàn toàn không có gì về cách các bộ sưu tập được thực sự thực hiện, hoặc sự khác biệt thực hiện giữa một mảng động và tĩnh. Bất kỳ thông tin chi tiết nào khác sẽ được đánh giá cao.
EDIT: Mã cho thử nghiệm bản thân (bằng cách sử dụng mảng động)
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
Và đối với những động lớp mảng 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
Và cuối cùng, các lớp đối tượng SpeedTester rất đơn giản :
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
tần suất bạn thay đổi kích thước chúng? VBA cho phép thay đổi kích thước mảng động thông qua 'redim preserve' nếu điều này không xảy ra thường xuyên và/hoặc bạn biết kích thước của mảng mới và sẽ cho phép bạn tiếp tục sử dụng mảng (thay vì tập hợp). – enderland
Có hay không có sự khác biệt nào đáng kể phụ thuộc vào trường hợp sử dụng chính xác của bạn. Dường như nó sẽ rất dễ dàng để thử nghiệm mặc dù: bạn có chạy bất kỳ so sánh? –