当前位置: 首页 > 知识库问答 >
问题:

VBA:变异数组与类型化数组与非键控集合的迭代速度

蒋鹏鹍
2023-03-14
Dim myObject As MyClass
Set myObject = variantList.Get(i)

另外,第二个选项会比使用非键控集合更快吗?我读到收集迭代很慢,它们是为查找而设计的。这适用于非键控集合,还是仅适用于键值映射集合?

感谢任何能提供建议的人。

共有1个答案

翟淇
2023-03-14

我听从了蒂姆·威廉姆斯的建议,做了一些速度测试。

对于每种类型的集合/数组,我首先添加了100,000个类“SpeedTester”的对象,它只是一个shell对象,包含一个长变量(具有get/set属性)。变量的值是循环索引的值(介于1和100,000之间)

然后我执行了第二个循环,其中涉及访问集合/数组中的每个对象,并将对象的long属性值赋给类型为long的新变量。我对每个方法执行3轮,并平均and和get循环的时间。

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

Dynamic array typed是一个自定义类,包含SpeedTester类型的数组。每次添加变量时,数组的大小将扩大1个槽(使用ReDim Proprese)。get-loop是一个for循环,使用1到100,000的索引,这是数组的典型情况。

最后,输入的静态数组只是一个SpeedTester类型的数组,它的初始值为100,000个插槽。显然这是最快的方法。奇怪的是,它的速度增长很大程度上是在获取而不是添加。由于需要调整大小,我假设其他方法的添加速度会更慢,而获取每个对象的速度不会比动态数组快。

我对使用for-loop和for-each loop访问索引集合的对象之间的差异感到惊讶。我还对映射集合的键查找速度感到惊讶--比索引快得多,可以与除静态数组之外的所有其他方法媲美。

编辑:测试本身的代码(使用动态数组)

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

对于动态数组类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

最后,非常简单的SpeedTester对象类:

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
 类似资料:
  • 我正在尝试编写一个突变查询,它可以完美地与图形ql配合使用 这些是查询变量 这就是graphql突变的样子,现在我正尝试在angular中使用Apollo Client来构建这种突变 但是由于Array类型的变量$env,我得到了Http失败响应。字符串类型的变量没有问题,但是数组对象导致了这个错误。

  • 问题内容: 如何在Go for map中将键创建为数组。例如在ruby中,我可以这样实现: Golang的外观如何? 问题答案: 数组类型(不像片)在Go具有可比性,所以在它什么神奇:你可以定义它像任何其他地图:这里会和会。 该比较操作符 ==和=必须为键类型的操作数被完全定义!; 因此,键类型不能为函数,映射或切片。 输出: 在Go Playground上尝试一下。 要查询元素: 您还可以一步创

  • 问题内容: 在Java中,我需要从我的方法中返回一个Iterator。我的数据来自另一个对象,该对象通常可以给我一个迭代器,因此我可以返回它,但是在某些情况下,基础数据为null。为了保持一致,在这种情况下,我想返回一个“空”迭代器,这样我的调用者就不必测试null。 我想写一些类似的东西: 但是Java编译器抱怨返回而不是。投射到也不起作用。 问题答案: 您可以通过以下语法获取Foo类型的空列表

  • JavaScript中有没有已知的技巧来区分和之间的区别,而不触发迭代? 我正在尝试实现以下类型检查器: 我知道调用会告诉我们这一点,但在无法触发迭代时我需要它。 此外,即使我在TypeScript中给出了示例,我也需要在运行时严格检查它。

  • 问题内容: 有没有更好的方法来实现这一目标? 注意: Arrays.asList(a)返回由指定数组支持的固定大小的列表。 (将返回的列表更改为“直写”到数组。)。我不要那种行为 我认为我上面的功能绕过了(或者我错了吗?) 因此,这里有另一种方法: 只看它, 我相信它比第一种方法更快 。 问题答案: 您用更好的方式表示什么: 更具可读性: 更少的内存消耗,并且可能更快(但绝对不是线程安全的): 顺

  • 问题内容: 关于so​​rt()的Collections与Arrays这两个关于sort()方法的区别是什么?我知道Arrays的sort()使用二进制搜索进行sort(),那么Collections呢?以及如何选择使用哪个?谢谢! 问题答案: 那么,除了在不同的东西操作(操作上,以及在阵列上运行),简单地调用做繁重。 另外,请注意运行合并排序的价值。