performance - 迭代 Scripting.Dictionary/Collection 对象

标签 performance vba collections dictionary iteration

我有一个项目,在过去的几年里进行了一点点的改变和修改,从一个代码模块到下一个代码模块,很多都是非标准化的。在某些情况下,我使用 Scripting.Dictionary 对象,而在其他情况下,我使用 Collection 对象。对于其中的每一个,有时会按计数进行迭代(即 For i = 1 to Obj.Count),有时会按 For...Each 进行迭代。

我想对尽可能多的情况应用相同的逻辑,以使 future 的更改更加无缝,但我不确定哪种方法最好。 (我相信某些特定情况是针对一种或另一种方法进行的,但我也很确定某些代码可以使用任何可用的方法。)

我尝试创建一个测试子来帮助我确定哪种方法效果最好,但结果有些不一致。总的来说,循环遍历 Dictionary 中的每个 Item 似乎更快,但在某些情况下,我的测试结果显示循环遍历每个 ItemCollection 中速度更快。差异可能取决于任何给定时间系统中发生的所有其他事情。

我想知道是否有人对哪种方法始终是最快的有明确的答案,假设循环中的所有其他内容都是相同的。或者,是否有某种方法可以改进我的测试子,使其在返回结果时更加一致,以便我可以自己回答这个问题?

我想出的测试代码:

Option Explicit

Sub Test_Dictionary_Iteration_Speed()

Dim Coll1 As New Collection, Coll2 As New Collection
Dim Dict1 As New Scripting.Dictionary, Dict2 As New Scripting.Dictionary, Dict3 As New Scripting.Dictionary
Dim i As Integer, j As Integer, l As Integer
Dim StartTime As Single, StopTime As Single
Dim v As Variant
Dim Obj As TestObject 'A custom Class that has only one member variable, MainVal, and no functions/subs

    For i = 0 To 32766
        Set Obj = New TestObject
        Obj.MainVal = i
        Dict1.Add CStr(i), Obj
        Dict2.Add CStr(i), Obj
        Dict3.Add CStr(i), Obj
        Coll1.Add Obj, CStr(i)
        Coll2.Add Obj, CStr(i)
    Next i

    StartTime = Timer()

    For j = 0 To Dict1.Count - 1
        l = CInt(Dict1(CStr(j)).MainVal)
        Set Obj = Dict1(CStr(l)) 'Do something useful within the loop
        Set Obj = Nothing
        Dict1.Remove CStr(l)
    Next j

    StopTime = Timer()

    Debug.Print "Dict1 for x to y: " & StopTime - StartTime

    StartTime = Timer()

    For Each v In Dict2.Items
        l = CInt(v.MainVal)
        Set Obj = Dict2(CStr(l))
        Set Obj = Nothing
        Dict2.Remove CStr(l)
    Next v

    StopTime = Timer()

    Debug.Print "Dict2 for each item: " & StopTime - StartTime

    StartTime = Timer()

    For Each v In Dict3.Keys
        l = CInt(Dict3(v).MainVal)
        Set Obj = Dict3(CStr(l))
        Set Obj = Nothing
        Dict3.Remove CStr(l)
    Next v

    StopTime = Timer()

    Debug.Print "Dict3 for each key: " & StopTime - StartTime

    '---------- Division between Dictionary and Collection

    StartTime = Timer()

    For j = 0 To Coll1.Count - 1
        l = CInt(Coll1(CStr(j)).MainVal)
        Set Obj = Coll1(CStr(l))
        Set Obj = Nothing
        Coll1.Remove CStr(l)
    Next j

    StopTime = Timer()

    Debug.Print "Coll1 for x to y: " & StopTime - StartTime

    StartTime = Timer()

    For Each v In Coll2
        l = CInt(v.MainVal)
        Set Obj = Coll2(CStr(l))
        Set Obj = Nothing
        Coll2.Remove CStr(l)
    Next v

    StopTime = Timer()

    Debug.Print "Coll2 for each item: " & StopTime - StartTime

    Debug.Print vbNewLine & "-----" & vbNewLine   


End Sub

真实的输出示例,表明“最佳”选项并不总是相同:

Dict1 for x to y: 0.2011719
Dict2 for each item: 0.1738281
Dict3 for each key: 0.2167969
Coll1 for x to y: 0.2050781
Coll2 for each item: 0.1386719


Dict1 for x to y: 0.1875
Dict2 for each item: 0.171875
Dict3 for each key: 0.234375
Coll1 for x to y: 0.2050781
Coll2 for each item: 0.1542969


Dict1 for x to y: 0.25
Dict2 for each item: 0.21875
Dict3 for each key: 0.265625
Coll1 for x to y: 0.234375
Coll2 for each item: 0.171875


Dict1 for x to y: 0.265625
Dict2 for each item: 0.203125
Dict3 for each key: 0.296875
Coll1 for x to y: 0.234375
Coll2 for each item: 0.21875


Dict1 for x to y: 0.265625
Dict2 for each item: 0.1875
Dict3 for each key: 0.234375
Coll1 for x to y: 0.203125
Coll2 for each item: 0.15625


Dict1 for x to y: 0.28125
Dict2 for each item: 0.1875
Dict3 for each key: 0.25
Coll1 for x to y: 0.234375
Coll2 for each item: 0.1875


Dict1 for x to y: 0.28125
Dict2 for each item: 0.21875
Dict3 for each key: 0.328125
Coll1 for x to y: 0.234375
Coll2 for each item: 0.234375

最佳答案

除非您确实知道给定语句或过程的执行时间是一个问题,否则您不应该在优化上浪费人力。首先设计和调试,然后如果您认为事情太慢(它们可能不会),分析,然后才优化(执行时间通常会浪费在与您想象的完全不同的地方)。

For Each 结构很好、简洁、整洁。不使用它的唯一原因是如果您要从循环的集合中删除项目。那么你就有可能跳过某些项目。如果您打算删除项目,请向后循环索引。

关于performance - 迭代 Scripting.Dictionary/Collection 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11122074/

相关文章:

performance - 使两个直方图成比例的算法,最小化了删除的单位

.net - 海量数据快速可视化的方法

vba - Excel VBA 中大约每 10,000 次迭代出现无法解释的类型不匹配错误

java - 使用 java Collections.sort() 对 List<List<Integer>> 进行排序

Java:根据匹配的字符串/模式对数组进行排序

performance - 如何减少第一字节时间或第一加载时间

javascript - 如何使用 import() 在代码拆分中导入一个类?

sql-server - VBA 可以通过 SSL 证书连接到 SQL 服务器吗?

vba - FileSystemObject 代码已经开始抛出错误

php - 如何获取 Laravel 集合中元素的索引