ZetCode

Visual Basic 集合

最后修改于 2023 年 10 月 18 日

在本章中,我们将讨论 Visual Basic 集合。 .NET 框架提供了用于数据存储和检索的专用类。 在上一章中,我们描述了数组。 集合是数组的增强功能。

Visual Basic 中有两种不同的集合类型。 标准集合位于 System.Collections 命名空间下,泛型集合位于 System.Collections.Generic 下。 泛型集合更灵活,是处理数据的首选方式。 泛型集合或泛型是在 .NET 框架 2.0 中引入的。 泛型增强了代码重用、类型安全性和性能。

泛型编程 是一种计算机编程风格,其中算法是根据待指定的类型编写的,这些类型随后在需要时为作为参数提供的特定类型进行实例化。 这种方法由 Ada 在 1983 年率先提出,允许编写仅在其使用时操作的类型集合不同的通用函数或类型,从而减少重复。(维基百科)

ArrayList

ArrayList 是来自标准 System.Collections 命名空间的集合。 它是一个动态数组。 它提供对其元素的随机访问。 ArrayList 会在添加数据时自动扩展。 与数组不同,ArrayList 可以保存多种数据类型的数据。 通过整数索引访问 ArrayList 中的元素。 索引从零开始。 元素的索引和在 ArrayList 的末尾插入和删除需要恒定时间。 在动态数组的中间插入或删除元素成本更高。 它需要线性时间。

Program.vb
Option Strict On

Imports System.Collections

Module Example

    Class Empty

    End Class


    Sub Main()

        Dim da As ArrayList = New ArrayList()

        da.Add("Visual Basic")
        da.Add(344)
        da.Add(55)
        da.Add(New Empty)
        da.Remove(55)

        For Each el As Object In da
            Console.WriteLine(el)
        Next

    End Sub

End Module

在上面的示例中,我们创建了一个 ArrayList 集合。 我们向其中添加了一些元素。 它们具有各种数据类型:一个字符串、两个整数和一个类对象。

Imports System.Collections

为了使用 ArrayList 集合,我们需要导入 System.Collections 命名空间。

Dim da As ArrayList = New ArrayList()

创建了 ArrayList 集合。

da.Add("Visual Basic")
da.Add(344)
da.Add(55)
da.Add(New Empty)

我们使用 Add 方法向数组添加了五个元素。

da.Remove(55)

我们删除一个元素。

For Each el As Object In da
    Console.WriteLine(el)
Next

我们遍历数组并将其元素打印到控制台。

List

List 是一个强类型的对象列表,可以通过索引访问。 它可以在 System.Collections.Generic 命名空间下找到。

Program.vb
Option Strict On

Imports System.Collections.Generic

Module Example

    Sub Main()

        Dim langs As New List(Of String)
        langs.Add("Java")
        langs.Add("C#")
        langs.Add("C")
        langs.Add("C++")
        langs.Add("Ruby")
        langs.Add("Javascript")

        Console.WriteLine(langs.Contains("C#"))

        Console.WriteLine(langs(1))
        Console.WriteLine(langs(2))

        langs.Remove("C#")
        langs.Remove("C")

        Console.WriteLine(langs.Contains("C#"))

        langs.Insert(4, "Haskell")

        langs.Sort()

        For Each lang As String In langs
            Console.WriteLine(lang)
        Next

    End Sub

End Module

在前面的示例中,我们使用了 List 集合。

Imports System.Collections.Generic

为了使用 List 集合,我们需要导入 System.Collections.Generic 命名空间。

Dim langs As New List(Of String)

创建了一个泛型动态数组。 我们使用 Of 关键字指定我们使用字符串。

langs.Add("Java")
langs.Add("C#")
langs.Add("C")
...

我们使用 Add 方法向 List 添加元素。

Console.WriteLine(langs.Contains("C#"))

我们使用 Contains 方法检查 List 是否包含特定的字符串。

Console.WriteLine(langs(1))
Console.WriteLine(langs(2))

我们使用索引符号访问 List 的第二个和第三个元素。

langs.Remove("C#")
langs.Remove("C")

我们从 List 中删除了两个字符串。

langs.Insert(4, "Haskell")

我们在特定位置插入了一个字符串。

langs.Sort()

我们使用 Sort 方法对元素进行排序。

$ dotnet run
True
C#
C
False
C++
Haskell
Java
Javascript
Ruby

该示例的结果。

LinkedList

LinkedList 是 Visual Basic 中的一个泛型双向链表。 LinkedList 仅允许顺序访问。 LinkedList 允许进行恒定时间的插入或删除,但仅允许对元素的顺序访问。 由于链表需要额外的存储空间来存储引用,因此它们对于小的字符数据项列表(例如字符)来说是不切实际的。 与动态数组不同,可以向链表中添加任意数量的项(当然,受内存限制),而无需重新分配,这是一个昂贵的操作。

Program.vb
Option Strict On

Imports System.Collections.Generic

Module Example

    Sub Main()

        Dim nums As New LinkedList(Of Integer)

        nums.AddLast(23)
        nums.AddLast(34)
        nums.AddLast(33)
        nums.AddLast(11)
        nums.AddLast(6)
        nums.AddFirst(9)
        nums.AddFirst(7)

        Dim node as LinkedListNode(Of Integer)

        node = nums.Find(6)
        nums.AddBefore(node, 5)

        For Each num As Integer In nums
            Console.WriteLine(num)
        Next

    End Sub

End Module

这是一个带有某些方法的 LinkedList 示例。

Dim nums As New LinkedList(Of Integer)

这是一个整数 LinkedList。

nums.AddLast(23)
...
nums.AddFirst(9)

我们使用 AddLastAddFirst 方法填充链表。

Dim node as LinkedListNode(Of Integer)

node = nums.Find(6)
nums.AddBefore(node, 5)

LinkedList 由节点组成。 我们找到一个特定的节点,并在其之前添加一个元素。

For Each num As Integer In nums
    Console.WriteLine(num)
Next

将所有元素打印到控制台。

Dictionary

字典,也称为关联数组,是唯一键和值集合的集合,其中每个键都与一个值相关联。 检索和添加值非常快。 字典需要更多内存,因为对于每个值,也有一个键。

Program.vb
Option Strict On

Imports System.Collections.Generic

Module Example

    Sub Main()

        Dim domains As New Dictionary(Of String, String)

        domains.Add("de", "Germany")
        domains.Add("sk", "Slovakia")
        domains.Add("us", "United States")
        domains.Add("ru", "Russia")
        domains.Add("hu", "Hungary")
        domains.Add("pl", "Poland")

        Console.WriteLine(domains("sk"))
        Console.WriteLine(domains("de"))

        Console.WriteLine("Dictionary has {0} items", domains.Count)

        Console.WriteLine("Keys of the dictionary:")

        Dim keys As Dictionary(Of String, String).KeyCollection = domains.Keys

        For Each key As String In keys
            Console.WriteLine("{0}", key)
        Next

        Console.WriteLine("Values of the dictionary:")

        Dim vals As Dictionary(Of String, String).ValueCollection = domains.Values

        For Each val As String In vals
            Console.WriteLine("{0}", val)
        Next

        Console.WriteLine("Keys and values of the dictionary:")

        For Each kvp As KeyValuePair(Of String, String) In domains
            Console.WriteLine("Key = {0}, Value = {1}",
                kvp.Key, kvp.Value)
        Next

    End Sub

End Module

我们有一个字典,我们将域名映射到它们所在的国家/地区名称。

Dim domains As New Dictionary(Of String, String)

我们创建了一个具有字符串键和值的字典。

domains.Add("de", "Germany")
domains.Add("sk", "Slovakia")
domains.Add("us", "United States")
...

我们向字典中添加了一些数据。 第一个字符串是键。 第二个是值。

Console.WriteLine(domains("sk"))
Console.WriteLine(domains("de"))

在这里,我们通过它们的键检索了两个值。

Console.WriteLine("Dictionary has {0} items",
    domains.Count)

我们通过引用 Count 属性来打印项目的数量。

Dim keys As Dictionary(Of String, String).KeyCollection = domains.Keys

For Each key As String In keys
    Console.WriteLine("{0}", key)
Next

这些行从字典中检索所有键。

Dim vals As Dictionary(Of String, String).ValueCollection = domains.Values

For Each val As String In vals
    Console.WriteLine("{0}", val)
Next

这些行从字典中检索所有值。

For Each kvp As KeyValuePair(Of String, String) In domains
    Console.WriteLine("Key = {0}, Value = {1}",
        kvp.Key, kvp.Value)
Next

最后,我们打印字典的键和值。

$ dotnet run 
Slovakia
Germany
Dictionary has 6 items
Keys of the dictionary:
de
sk
us
ru
hu
pl
Values of the dictionary:
Germany
Slovakia
United States
Russia
Hungary
Poland
Keys and values of the dictionary:
Key = de, Value = Germany
Key = sk, Value = Slovakia
Key = us, Value = United States
Key = ru, Value = Russia
Key = hu, Value = Hungary
Key = pl, Value = Poland

队列

队列 是一种先入先出 (FIFO) 数据结构。 添加到队列中的第一个元素将是要删除的第一个元素。 队列可用于处理按出现的顺序排列的消息,或为到达的客户提供服务。 首先到达的客户应首先获得服务。

Program.vb
Option Strict On

Imports System.Collections.Generic

Module Example

    Sub Main()

        Dim msgs As New Queue(Of String)

        msgs.Enqueue("Message 1")
        msgs.Enqueue("Message 2")
        msgs.Enqueue("Message 3")
        msgs.Enqueue("Message 4")
        msgs.Enqueue("Message 5")

        Console.WriteLine(msgs.Dequeue())
        Console.WriteLine(msgs.Peek())
        Console.WriteLine(msgs.Peek())

        Console.WriteLine()

        For Each msg As String In msgs
            Console.WriteLine(msg)
        Next

    End Sub

End Module

在我们的示例中,我们有一个包含消息的队列。

Dim msgs As New Queue(Of String)

创建了一个字符串队列。

msgs.Enqueue("Message 1")
msgs.Enqueue("Message 2")
...

Enqueue 将消息添加到队列的末尾。

Console.WriteLine(msgs.Dequeue())

Dequeue 方法删除并返回队列开头的项目。

Console.WriteLine(msgs.Peek())

Peek 方法返回队列中的下一个项目,但不会将其从集合中删除。

$ dotnet run
Message 1
Message 2
Message 2

Message 2
Message 3
Message 4
Message 5

Dequeue 方法从集合中删除“Message 1”。 Peek 方法不会。 “Message 2”保留在集合中。

是一种后进先出 (LIFO) 数据结构。 添加到队列中的最后一个元素将是要删除的第一个元素。 C 语言使用堆栈来存储函数中的本地数据。 堆栈也用于实现计算器。

Program.vb
Option Strict On

Imports System.Collections.Generic

Module Example

    Sub Main()

        Dim stc As New Stack(Of Integer)

        stc.Push(1)
        stc.Push(4)
        stc.Push(3)
        stc.Push(6)
        stc.Push(4)

        Console.WriteLine(stc.Pop())
        Console.WriteLine(stc.Peek())
        Console.WriteLine(stc.Peek())

        Console.WriteLine()

        For Each item As Integer In stc
            Console.WriteLine(item)
        Next

    End Sub

End Module

我们在上面有一个简单的堆栈示例。

Dim stc As New Stack(Of Integer)

创建了 Stack 数据结构。

stc.Push(1)
stc.Push(4)
...

Push 方法将一个项目添加到堆栈的顶部。

Console.WriteLine(stc.Pop())

Pop 方法从堆栈的顶部删除并返回该项目。

Console.WriteLine(stc.Peek())

Peek 方法返回堆栈顶部的项目。 它不会将其删除。

$ dotnet run
4
6
6

6
3
4
1

Visual Basic 教程的这一部分专门介绍了 Visual Basic 中的集合。