Skip to content
AgileLogics
6 min read

Collections: List and Dictionary

Prerequisites: Arrays

Arrays have a fixed size. The generic collections in System.Collections.Generic grow and shrink as needed.

List(Of T)

Module Program
    Sub Main()
        Dim items As New List(Of String) From {"apple", "banana"}
        items.Add("cherry")
        items.Insert(0, "avocado")
        items.Remove("banana")

        Console.WriteLine(items.Count)
        Console.WriteLine(items(1))
        Console.WriteLine(items.Contains("cherry"))
        Console.WriteLine(items.IndexOf("cherry"))

        items.Sort()
        Console.WriteLine(String.Join(", ", items))

        For Each item In items
            Console.Write(item.ToUpper() & " ")
        Next
        Console.WriteLine()
    End Sub
End Module
3
apple
True
2
apple, avocado, cherry
APPLE AVOCADO CHERRY

(Of String) is the type argument: a List(Of String) holds only strings, and the compiler checks every Add. From { ... } is a collection initializer.

Dictionary(Of TKey, TValue)

A dictionary maps keys to values with fast lookup:

Module Program
    Sub Main()
        Dim capitals As New Dictionary(Of String, String) From {
            {"France", "Paris"},
            {"Japan", "Tokyo"}
        }
        capitals("Kenya") = "Nairobi"       ' add or replace
        capitals.Add("Peru", "Lima")        ' add (throws if the key exists)

        Console.WriteLine(capitals("Japan"))
        Console.WriteLine(capitals.ContainsKey("Chile"))

        Dim city As String = Nothing
        If capitals.TryGetValue("Peru", city) Then Console.WriteLine($"Peru -> {city}")

        capitals.Remove("France")
        For Each pair In capitals
            Console.WriteLine($"{pair.Key}: {pair.Value}")
        Next
    End Sub
End Module
Tokyo
False
Peru -> Lima
Japan: Tokyo
Kenya: Nairobi
Peru: Lima

Reading a missing key with capitals("Chile") throws a KeyNotFoundException; TryGetValue is the safe way.

Counting with a dictionary

Module Program
    Sub Main()
        Dim counts As New Dictionary(Of String, Integer)
        For Each word In "to be or not to be".Split(" "c)
            If counts.ContainsKey(word) Then
                counts(word) += 1
            Else
                counts(word) = 1
            End If
        Next
        For Each pair In counts
            Console.WriteLine($"{pair.Key} = {pair.Value}")
        Next
    End Sub
End Module
to = 2
be = 2
or = 1
not = 1

Other collections

Collection Use for
HashSet(Of T) unique items, fast "contains" checks
Queue(Of T) first in, first out (Enqueue, Dequeue)
Stack(Of T) last in, first out (Push, Pop)
SortedDictionary(Of K, V) a dictionary kept in key order
Module Program
    Sub Main()
        Dim seen As New HashSet(Of Integer)
        Console.WriteLine(seen.Add(5))
        Console.WriteLine(seen.Add(5))

        Dim line As New Queue(Of String)
        line.Enqueue("first")
        line.Enqueue("second")
        Console.WriteLine(line.Dequeue())

        Dim undo As New Stack(Of String)
        undo.Push("typed a")
        undo.Push("typed b")
        Console.WriteLine(undo.Pop())
    End Sub
End Module
True
False
first
typed b

Older code uses the non-generic ArrayList, Hashtable, and VB6's Collection object, which store Objects and need casting. Prefer the generic types.

Practice

Store product names and prices in a Dictionary(Of String, Decimal), then print every product under 5 and the total price of all products.

Show solution
Module Program
    Sub Main()
        Dim prices As New Dictionary(Of String, Decimal) From {
            {"Tea", 3.5D}, {"Cake", 6D}, {"Coffee", 4.25D}
        }
        Dim total = 0D
        For Each pair In prices
            If pair.Value < 5D Then Console.WriteLine($"{pair.Key}: {pair.Value}")
            total += pair.Value
        Next
        Console.WriteLine($"Total: {total}")
    End Sub
End Module
Tea: 3.5
Coffee: 4.25
Total: 13.75