1
\$\begingroup\$

I’ve wrote a small array wrapper class which mimics the built-in Collection for adding and retrieving items. Once the object is created, you set the array capacity and that would not change.

'// ArrayList Class

Private arr() As String
Private position As Long

' Add
Public Sub Add(ByVal Value As String)
    arr(position) = Value
    position = position + 1
End Sub

' Count
Public Function Count() As Long
    Count = UBound(arr)
End Function

' Item
Public Function Item(ByVal Index As Long) As String
    Item = arr(Index)
End Function

' SetCapacity
Public Sub SetCapacity(ByVal arrsize As Long)
    ReDim arr(arrsize)
End Sub

Testing the object:

Sub TestArrayList()

    Dim a As ArrayList
    Set a = New ArrayList
        a.SetCapacity 4

        a.Add "One"
        a.Add "Two"
        a.Add "Three"
        a.Add "Four"
        a.Add "Five"

    Dim i As Long
    For i = 0 To a.Count
        Debug.Print a.Item(i)
    Next i
End Sub

'Output as expected
'One
'Two
'Three
'Four
'Five

It is widely known that expensive operations of an array are ReDim Preserve where a new array is created and the items of the old array are being copied.

In the object above, we only create a new array when calling the SetCapacity(arrsize) method. No need to preserve any items. Thus the expensive operation here is the creation of the new array (fixed size) which is only performed once.

The question in terms of speed and overhead is: would a built-in collection be more appropriate than the above wrapper object?

The aim is to create a Collection of objects but I'm not sure which would be more appropriate, a Collection(Of Collection) or a Collection(Of ArrayList).

In terms of data, the ArrayList will hold around 16 elements and the Collection around 1,500 objects.

\$\endgroup\$
  • \$\begingroup\$ Why not use a Scripting.Dictionary? \$\endgroup\$ – ThunderFrame Oct 21 '17 at 23:10
  • \$\begingroup\$ @ThunderFrame Thanks but what is the benefit of using a dictionary in this case? I still need a collection (or dictionary) that holds arrays (or collections). \$\endgroup\$ – Kostas K. Oct 22 '17 at 5:41
  • \$\begingroup\$ Can't see any advantage from using a plain array - Ok, position is automatic while Adding... \$\endgroup\$ – LS_ᴅᴇᴠ Oct 26 '17 at 13:13
  • \$\begingroup\$ What do you mean by "In terms of data, the ArrayList will hold around 16 elements and the Collection around 1,500 objects."? Count should equal position - 1. You could add a getCapacity method that equals arr(arrsize) but in the VBA I would makeCapacity a property. \$\endgroup\$ – user109261 Oct 29 '17 at 15:42
  • 1
    \$\begingroup\$ If you want to emulate your own ArrayList class for the learning experience, you might want to look at my post VBA Class to Encapsulate the System.Collections.ArrayList Class . \$\endgroup\$ – user109261 Oct 29 '17 at 16:45
3
\$\begingroup\$

I hold issue with the way you determine your wrapper's size -

Public Sub SetCapacity(ByVal arrsize As Long)
    ReDim arr(arrsize)
End Sub

The arrsize I pass will be 0-based, so if I want 5, I have to put 4. Not intuitive. Instead

RedDim arr(1 to arrsize)

And then there's not really any reason for this

Public Function Count() As Long
    Count = UBound(arr)
End Function

Because your iterations would be LBound(arr) to Ubound(arr).


Also, I think holding the position in a class level variable is kind of sloppy. Like was mentioned in the comments, there are built-in objects that can do this for you - there's no real reason to reinvent the wheel here.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.