# Visual Basic 中的集合

> 原文： [https://zetcode.com/lang/visualbasic/collections/](https://zetcode.com/lang/visualbasic/collections/)

在本章中，我们将处理 Visual Basic 集合。 .NET 框架为数据存储和检索提供了专门的类。 在上一章中，我们描述了数组。 集合是对数组的增强。

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

通用编程是一种计算机编程样式，其中，算法根据待指定的后来的类型编写，然后在需要作为参数提供的特定类型时实例化。 这种方法由 Ada 于 1983 年率先提出，它允许编写仅在使用时所使用的类型集不同的常见功能或类型，从而减少了重复。 （维基百科）

## `ArrayList`

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

```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`集合。 我们添加了一些元素。 它们具有各种数据类型：一个字符串，两个整数和一个类对象。

```vb
Imports System.Collections

```

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

```vb
Dim da As ArrayList = New ArrayList()

```

`ArrayList`集合已创建。

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

```

我们使用`Add()`方法将五个元素添加到数组中。

```vb
da.Remove(55)

```

我们删除一个元素。

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

```

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

## `List`

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

```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`集合。

```vb
Imports System.Collections.Generic

```

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

```vb
Dim langs As New List(Of String)

```

将创建一个通用动态数组。 我们指定将使用带有`Of`关键字的字符串。

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

```

我们使用`Add()`方法将元素添加到列表中。

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

```

我们使用`Contains()`方法检查列表是否包含特定的字符串。

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

```

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

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

```

我们从列表中删除两个字符串。

```vb
langs.Insert(4, "Haskell")

```

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

```vb
langs.Sort()

```

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

```vb
$ ./list.exe 
True
C#
C
False
C++
Haskell
Java
Javascript
Ruby

```

示例的结果。

## `LinkedList`

`LinkedList`是 Visual Basic 中的通用双链表。 `LinkedList`仅允许顺序访问。 `LinkedList`允许进行固定时间的插入或删除，但只允许顺序访问元素。 由于链接列表需要额外的存储空间以供参考，因此对于诸如字符之类的小型数据项列表来说，它们是不切实际的。 与动态数组不同，可以将任意数量的项目添加到链接列表（当然受内存限制）而无需重新分配，这是一项昂贵的操作。

```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`示例，其中包含一些方法。

```vb
Dim nums As New LinkedList(Of Integer)

```

这是一个整数`LinkedList`。

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

```

我们使用`AddLast()`和`AddFirst()`方法填充链表。

```vb
Dim node as LinkedListNode(Of Integer)

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

```

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

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

```

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

## `Dictionary`

`dictionary`，也称为关联数组，是唯一键和值的集合，其中每个键与一个值相关联。 检索和添加值非常快。 字典占用更多内存，因为每个值都有一个键。

```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

```

我们有一本字典，我们在其中将域名映射到其国家名称。

```vb
Dim domains As New Dictionary(Of String, String)

```

我们创建一个包含字符串键和值的字典。

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

```

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

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

```

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

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

```

我们通过参考`Count`属性来打印项目数。

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

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

```

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

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

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

```

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

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

```

最后，我们同时打印字典的键和值。

```vb
./dictionary.exe
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

```

这是示例的输出。

## `queue`

`queue`是先进先出（FIFO）数据结构。 添加到队列中的第一个元素将是第一个要删除的元素。 队列可以用于处理消息出现时的消息，也可以用于消息到达时为客户服务的消息。 首先服务的是第一个客户。

```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

```

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

```vb
Dim msgs As New Queue(Of String)

```

创建字符串队列。

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

```

`Enqueue()`将消息添加到队列末尾。

```vb
Console.WriteLine(msgs.Dequeue())

```

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

```vb
Console.WriteLine(msgs.Peek())

```

`Peek()`方法从队列中返回下一项，但不会将其从集合中删除。

```vb
$ ./queue.exe 
Message 1
Message 2
Message 2

Message 2
Message 3
Message 4
Message 5

```

`Dequeue()`方法从集合中删除“消息 1”。 `Peek()`方法没有。 “消息 2”保留在集合中。

## `stack`

`stack`是后进先出（LIFO）数据结构。 添加到队列中的最后一个元素将是第一个要删除的元素。 C 语言使用栈将本地数据存储在函数中。 实现计算器时，还将使用该栈。

```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

```

上面有一个简单的栈示例。

```vb
Dim stc As New Stack(Of Integer)

```

创建一个`Stack`数据结构。

```vb
stc.Push(1)
stc.Push(4)
...

```

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

```vb
Console.WriteLine(stc.Pop())

```

`Pop()`方法从栈顶部删除并返回该项目。

```vb
Console.WriteLine(stc.Peek())

```

`Peek()`方法从栈顶部返回该项目。 它不会删除它。

```vb
$ ./stack.exe 
4
6
6

6
3
4
1

```

输出。

Visual Basic 教程的这一部分专用于 Visual Basic 中的集合。