Можете
да мислите за класа ArrayList като
хибрид от Array и Collection обекти, при
което можете да работите с множество от стойности като че ли са масиви и колекции едновременно. Примерно можете да адресирате елементите по
техните индекси, да ги сортирате, реверсирате (подреждате отзад напред) и
търсите по последователността на стойностите или двоично както се прави при
масиви; можете да добавяте елементи, да ги вмъквате на дадена позиция или да ги
изтривате както правите при колекции. Обектът ArrayList има инициализиран капацитет--броя на слотовете във
външната структура, която държи актуалните стойности - но ArrayList може автоматично да се разширява при нужда както могат
колекциите. Въпреки това можете да оптимизирате кода си като изберете да
инициализирате капацитета на ArrayList,
като добър компромис между използвана памет и опасност от препокриване при
разширяване на ArrayList.
` Създаване на
ArrayList с капацитет по подразбиране от 11 елемента.
Dim al As New ArrayList
`Създаване на ArrayList с капацитет от 1000 елемента.
Dim al2 As New ArrayList(1000)
Можете
да модифицирате капацитета , за да го разширите или свиете по всяко време чрез
свойство Capacity. Но не можете да
го направите по-малък от текущо съхранените елементи в масива, (което кореспондира
със стойността на свойство Count):
` ArrayList заема точно толкова място в паметта, колкото
е нужно.
al.Capacity = al.Count
` Друг начин за постигане на същия резултат
al.TrimToSize
Когато
текущият капацитет се разшири, обектът ArrayList
удвоява своя капацитет автоматично.
Друг
начин за създаване на обект ArrayList
е чрез споделения метод Repeat, който
ви позволява да определите инициализиращата стойност за броя на елементите:
` Създаване на ArrayList със 100 елемента равни на нулев
стринг.
Dim al As ArrayList = ArrayList.Repeat("", 100)
Класът
ArrayList напълно представлява
интерфейса IList interface. Можете да прибавите елементи
към обект ArrayList като използвате
метод Add (който добавя елемент след последния член (item) или метод Insert (който
вмъква на определен индекс). Можете да изтриете обект с метод Remove, или да изтриете елемент на
дадена позиция чрез метод RemoveAt, а
може да изтриете всички елементи с метод Clear:
`Празен ArrayList.
al.Clear
` Добавяне на елементите "Pavel" и "Ana" на края на
списъка ArrayList.
al.Add("Pavel")
al.Add("Ana")
` Вмъкване на елемент "Robert" в началото на списъка.
(Индексите са 0-безирани.)
al.Insert(0, "Robert")
` Изтриване на "Pavel" от списъка.
al.Remove("Pavel")
` Изтриване на първия елемент от списъка("Robert" в
случая).
al.RemoveAt(0)
Методът Remove
изтрива само първия срещнат елемент, така че трябва да организирате цикъл за
изтриване на всички елементи със същата стойност. Не можете просто да
преминавате през цикъла до грешка, защото методът Remove не хваща грешка ако
елементът не е намерен. По тази причина трябва да използвате един от тези два
начина:
` Използвайки метод IndexOf .
` (може също метод Contains)
Do While al.IndexOf("element to remove") >= 0
al.Remove("element to remove")
Loop
` По-ефективна техника: циклене докато свойство Count
получи константа.
Dim saveCount As Integer
Do
saveCount = al.Count
al.Remove("element to remove")
Loop While al.Count < saveCount
Можете да
прочетете елемент от ArrayList чрез свойство Item.
Това е подразбиращото
се свойство (default), така че може да го пропуснете. Основната разлика между реалните масиви и
обектите ArrayList
е, че елементът на ArrayList се създава само когато се извика метод
Add,
така че не може да работите с елемент, чийто индекс е равен или по-голям на
свойството Count
на ArrayList:
al(0) = "first element"
Като при
колекциите, предпочитания начин за итерации е цикъл For Each:
Dim o As Object
For Each o In al
Console.WriteLine(o)
Next
Създаване на
ненулево базирани масиви (Nonzero-Based Arrays)
Методът GetLowerBound може да изглежда излишен,
защото всички масиви са нулево базирани, тоест започват с индекс 0. Въпреки това, има възможност да създадете масив
стартиращ от друг индекс чрез споделения метод Array.CreateInstance, макар че изискваният синтаксис е сложен:
Sub TestArraysWithNonZeroLBound()
' Създаване на двудименсионален масив, който е еквивалентен
' на следната Visual Basic 6 декларация:
' Dim(1 To 5, -10 To 10) As Integer
' Приготвяне на auxiliary array дължина за всяка дименсия.
Dim lengths() As Integer = {5, 21}
' auxiliary array със стартов индекс за всяка дименсия
Dim lbounds() As Integer = {1, -10}
' създаване на генеричен обект Array
object от
споделения CreateInstance метод.
Dim arrObj As Array = _
Array.CreateInstance(GetType(Integer), lengths, lbounds)
' присвояването му на масив с правилния ранг.
Dim arr(,) As Integer = CType(arrObj, Integer(,))
' изпробване дали това работи.
Console.WriteLine(arr.GetLowerBound(0)) ' => 1
Console.WriteLine(arr.GetUpperBound(0)) ' => 5
Console.WriteLine(arr.GetLowerBound(1)) ' => -10
Console.WriteLine(arr.GetUpperBound(1)) ' => 10
' присвояване на елемент, и прочитането му.
arr(1, -1) = 1234
Console.WriteLine(arr(1, -1)) ' => 1234
End Sub
Този начин е
добър за мулти-дименсионални масиви, но за едно-дименсионални не се препоръчва.
Копиране на
масиви (Copying Arrays)
Класът Array поддържа интерфейса ICloneable, така че можете да създадете
празно копие на масив използвайки методът за инстанциране Clone.
`работи ако Option Strict is Off.
Dim anotherArray(,) As Integer = arr.Clone
` този синтаксис се изисква ако Option
Strict is On.
` (може да използвате CType вместо DirectCast.)
Dim anotherArray(,) As Integer = DirectCast(arr.Clone,
Integer())
You can copy a one-dimensional array to another, and you
decide the starting index in the destination array:
` създадане и инициализираме на масив (10 елемента).
Dim sourceArr() As Integer = {1, 2, 3, 5, 7, 11, 13, 17,
19, 23}
`създаване на целеви масив (трябва да е със същия размер
или по-голям).
Dim destArr(20) As Integer
` копиране на масива източник във втората половина на целевия
масив.
sourceArr.CopyTo(destArr, 10)
Обърнете
внимание на важен детайл: индексът в целевия масив е актуално отместването от
стартовия индекс на масива. Ако целевия масив е 0-базиран (каквито са всички
масиви декларирани с оператор Dim), вие
можете да подадете индекса на първия елемент, който ще бъде презаписан в
целевия масив. Докато ако използвате Array.CreateInstance
за създаване на масив, чийто най-нисък индекс е различен от 0, вие трябва
съответно да модифицирате втория аргумент на метода CopyTo .
Примерно ако
масива е 1-базиран, подайте стойност 9 така че destArr(10) да е първият
презаписан елемент.
Сортиране на
елементи (Sorting Elements)
Класът Array предлага някои споделени методи
за процедиране с масиви лесно и бързо. Един от тях е метод Array.Sort. Вие можете да сортирате масиви, използвайки арбитражна
група от клавиши* под интерфейси IComparable
и IComparer.
Методът Sort е много гъвкав. Примерно, можете
да сортирате само порция от масив:
` сортиране само на елементите[10,100]
от
целевия масив targetArray.
` вторият аргумент е стартовия индекс; последния аргумент е
дължината на подмасива.
Array.Sort(targetArray, 10, 91)
Можете също
да сортирате масив от стойности използвайки друг масив, който съдържа
сортиращите ключове* , което ви позволява да сортирате масиви от структури или
обекти. За да се види как тази overloaded
версия на метод Sort работи, нека да
стартираме дефинирането на структура:
Structure Employee
Public FirstName As String
Public LastName As String
Public HireDate As Date
Sub New(ByVal firstName As String, ByVal lastName As _
String,ByVal hireDate As Date)
Me.FirstName = firstName
Me.LastName = lastName
Me.HireDate = hireDate
End Sub
' функция за лесно разпечатване на елементните свойства
Function Description() As String
Return FirstName & " " & LastName & _
" (hired on " & HireDate.ToShortDateString &
")"
End Function
End Structure
Следният код
създава главния масив (main array) на структурата Employee, която създава извънредния
ключов масив, който съдържа датата "hiring
date" на всеки служител (employee), и накрая сортира главния масив, използвайки
извънредния масив:
`създаване на тестов
масив.
Dim employees() As Employee = { _
New Employee("Pavel", "Doe", #3/1/2001#), _
New Employee("Robert", "Smith", #8/12/2000#),
_
New Employee("Ana", "Douglas", #11/1/1999#)}
` създаване на паралелен масив от hiring
dates.
Dim hireDates(UBound(employees)) As Date
Dim j As Integer
For j = 0 To employees.Length - 1
hireDates(j) = employees(j).HireDate
Next
` сортиране на масива
Employees използвайке
HireDates за ключове.
Array.Sort(hireDates, employees)
` пробване дали масивът е сортиран по поле
HireDate.
For j = 0 To employees.Length - 1
Console.WriteLine(employees(j).Description)
Next
Най-интересното
е, че ключовият масив е сортиран и затова не се нуждае от повторна
инициализация, когато се добавя друг елемент към главния масив:
` добавяне на четвърти служител (employee).
ReDim Preserve employees(3)
employees(3) = New Employee("Chris", "Doe",
#5/9/2000#)
`разшряване на ключовия масив -няма нужда от
повторна инизиализация.
ReDim Preserve hireDates(3)
hireDates(3) = employees(3).HireDate
`пресортиране на новия, по-дълъг масив.
Array.Sort(hireDates, employees)
Така overloaded версията на метода Sort ви дава възможност да сортирате
порция от масив от стойности, за които имате обезпечение от масива от ключове. Това
е особено полезно, когато стартирате с дълъг масив, който запълвате само на
порции"
`създаване на test
array с
много място.
Dim employees(1000) As Employee
`инициализация само на първите му четири елемента.
Array.Sort(hireDates, employees, 0, 4)
Всички версии
на метод Array.Sort могат да
използват допълнително обект IComparer,
който диктува как да се сравняват един с друг елементите или ключовете на
масива.
Методът Array.Reverse реверсира реда на
елементите на масива или на порцията от масива, така че може да се долепи
веднага след сортирането, за да се получи сортиране по обратен ред:
`сортиране на целочисления
масив в обратен (реверсивен) ред.
Array.Sort(intArray)
Array.Reverse(intArray)
Когато става
въпрос за порция от масив трябва да подадете началния индекс и броя на
елементите за реверсиране:
` реверсиране само на първите 10 елемента в масивintArray.
Array.Reverse(intArray, 0, 10)