I need to keep track of up to 100 values. When the list reaches 100, I'd
like the first to be removed and the new item added to the end. My first
thought was the Stack class, but I need to be able to update items 0-99
with updated values. The version I ended up with today is an ArrayList,
where I do...
If (myList.Count = 100) Then myList.RemoveAt(0)
myList.Add(newItem)
Does anyone have any suggestions for me? I'm not sure how expensive that
RemoveAt is.
Thanks!
Jason.
Jason,
Since you know that the queue is really going to be a fixed size
structure, I would suggest you implement your own queue class using an
array of items as the backing store. You could implement it as a
circular queue. Here is a very simple demonstration. You may want to
implement this as full typed collection, etc - but I just threw this
together to sort of demonstrate the algorithm... I believe I actually
learned this from an old VB algorithm book by Rod Stephens
I'm sure
that there maybe logical errors in this - but, the basic principal is
sound
Option Explicit On
Option Strict On
Public Class Form1
Inherits System.Windows.Forms.Form
#Region " Windows Form Designer generated code "
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after the InitializeComponent() call
End Sub
'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As
Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form
Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
Friend WithEvents Button1 As System.Windows.Forms.Button
Friend WithEvents ListBox1 As System.Windows.Forms.ListBox
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
Me.Button1 = New System.Windows.Forms.Button
Me.ListBox1 = New System.Windows.Forms.ListBox
Me.SuspendLayout()
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(108, 8)
Me.Button1.Name = "Button1"
Me.Button1.TabIndex = 0
Me.Button1.Text = "Button1"
'
'ListBox1
'
Me.ListBox1.IntegralHeight = False
Me.ListBox1.Location = New System.Drawing.Point(4, 40)
Me.ListBox1.Name = "ListBox1"
Me.ListBox1.Size = New System.Drawing.Size(288, 232)
Me.ListBox1.TabIndex = 1
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 273)
Me.Controls.Add(Me.ListBox1)
Me.Controls.Add(Me.Button1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
End Sub
#End Region
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim iq As New ItemQueue
Me.ListBox1.Items.Clear()
For i As Integer = 1 To 200
iq.Enqueue(New Item(i))
Next
For i As Integer = 1 To 100
Me.ListBox1.Items.Add(iq.Dequeue)
Next
End Sub
Private Class Item
Private _id As Integer
Public Sub New(ByVal id As Integer)
Me._id = id
End Sub
Public ReadOnly Property ID() As Integer
Get
Return Me._id
End Get
End Property
Public Overrides Function ToString() As String
Return _id.ToString()
End Function
End Class
Private Class ItemQueue
Private _items(99) As Item
Private _front As Integer
Private _back As Integer
Public Sub Enqueue(ByVal value As Item)
_items(_back) = value
_back = (_back + 1) Mod _items.Length
End Sub
Public Function Dequeue() As Item
Dim value As Item
value = _items(_front)
_items(_front) = Nothing
_front = (_front + 1) Mod _items.Length
Return value
End Function
End Class
End Class
Anyway, for your simple case (100 elements), I don't think your going to
gain a lot in performance. But with larger numbers of elements, an
array approach would definately be more efficient.