Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
(ebook) Visual Studio .NET Mastering Visual Basic.pdf
Скачиваний:
120
Добавлен:
17.08.2013
Размер:
15.38 Mб
Скачать

THE ARRAYLIST COLLECTION 489

A similar approach must be followed to make space for a new element. To insert a new element at the beginning of the array, all elements must be moved by one position toward the end of the array.

These problems were addressed with the introduction of a new structure, the ArrayList, which is described in the following section. In short, the ArrayList is a dynamic array that expands and shrinks automatically during the course of the program as needed.

Another shortcoming of arrays is that you can only access their elements by means of an index, which in most situations is a meaningless number. Ideally, we should be able to access arrays with a meaningful key. If the array Capitals contains the state capitals, the capital of California could be the element Capitals(0) or Capitals(33). It’s up to the programmer to come up with a technique to match states to indices. A far more convenient structure would be an array that can be accessed by a string, which in our example would be the name of the state: Capitals(“California”). The Framework provides two structures that resemble an array, but their elements can be accessed by a key: the HashTable and the Dictionary. The Dictionary is not new VB.NET—it has been around since VB4—but it’s being replaced by the HashTable. In this chapter, I will discuss the HashTable class in detail.

Both ArrayLists and HashTables are quite similar in terms of the members they expose, so I will present the members of the ArrayList collection in detail. Many of these members apply to both collections.

The ArrayList Collection

The ArrayList collection allows you to maintain multiple elements, similar to an array. However, the ArrayList collection allows the insertion of elements anywhere in the collection, as well as the removal of any element. In other words, it’s a dynamic structure that can also grow automatically as you add elements. Like an array, the ArrayList’s elements can be sorted and searched. In effect, the ArrayList is a more “convenient” array, a dynamic array. You can also remove elements by value, not only by index. If you have an ArrayList populated with names, you remove the item “Charles” by passing the string itself as argument. Notice that “Charles” is not an index value; it’s the element you want to remove.

Creating an ArrayList

To use an ArrayList in your code, you must first create an instance of the ArrayList class with the New keyword. When you declare an ArrayList, you need not specify any dimensions. Just use a statement like this one:

Dim aList As New ArrayList

The aList variable represents an ArrayList that can hold only 16 elements (the default size). You can set the initial capacity of the ArrayList by setting its Capacity property. The Capacity property is the number of elements the ArrayList can hold. It’s like declaring an array for 100 elements, but using only 4 of them. There are 96 more elements to be used. The ArrayList’s capacity can be increased, or reduced, at any time, just by setting the Capacity property. The following statement sets the capacity of the ArrayList to 1,000 elements:

aList.Capacity = 1000

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

490 Chapter 11 STORING DATA IN COLLECTIONS

The aList variable is now ready to hold a large number of items. Notice that you don’t have to prepare the collection for accepting a specific number of items. Every time you exceed the collection’s capacity, it’s doubled automatically. However, it’s not decreased automatically when you remove items.

The exact number of items currently in the ArrayList is given by the Count property, which is always less than (or, at most, equal to) the Capacity property. Both properties are expressed in terms of items, not bytes or any other unit that might involve additional calculations. If you decide that you’re no longer going to add more items to the collection, you can call the TrimToSize method, which will set the collection’s capacity to the number of items in the list. After calling the TrimToSize method, the Capacity property becomes equal to the Count property.

Adding and Removing Items

To add a new item to an ArrayList, use the Add method, whose syntax is

index = aList.Add(object)

where aList is a properly declared ArrayList and object is the item you want to add to the ArrayList collection (it could be a number, a string, or a custom object). The Add method appends the specified item to the collection and returns the index of the new item. If you’re using an ArrayList named Capitals to store the names of the state capitals, you can add an item (a string) with the following statement:

Capitals.Add(“Sacramento”)

If the Persons ArrayList holds variables of a custom type, prepare a variable of that type and then add it to the collection. Let’s say you’ve created a structure called Person with the following declaration:

Structure Person

Dim LastName As String

Dim FirstName As String

Dim Phone As String

Dim EMail As String

End Structure

To store a collection of Person items in an ArrayList, create a variable of the Person type, set its fields, and then add it to the ArrayList, as in Listing 11.3.

Listing 11.3: Adding a Structure to an ArrayList

Dim Persons As New ArrayList Dim p As New Person p.LastName = “Last Name” p.FirstName = “First Name” p.Phone = “Phone”

p.EMail = “name@server.com” Persons.Add(p)

p.LastName = “another name”

{ statements to set the other fields } Persons.Add(p)

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

THE ARRAYLIST COLLECTION 491

If you execute these statements, the ArrayList will hold two items, both of the Person type. Notice that you can add multiple instances of the same object to the ArrayList collection. To find out whether an item belongs to the collection already, use the Contains method, which accepts as argument an object and returns a True or False value, depending on whether the object belongs to the list:

If Persons.Contains(p) Then

MsgBox(“Duplicate element rejected”)

Else

Persons.Add(p)

End If

By default, items are appended to the ArrayList. To insert an item at a specific location, use the Insert method. The Insert method accepts as argument the location at which the new item will be inserted and, of course, an object to insert in the ArrayList, as shown next:

aList.Insert(index, object)

Unlike the Add method, the Insert method doesn’t return a value—the location of the new item is already known.

You can also add multiple items with a single call to the AddRange method. This method appends a collection of items to the ArrayList. The items could come from an array, or another ArrayList. The following statement appends the elements of an array to the aList collection:

Dim colors() As Color = {Color.Red, Color.Blue, Color.Green} aList.AddRange(colors)

The AddRange method in this example has appended three items of the same type to the ArrayList collection. The array could have been declared as Object too; it doesn’t have to be strictly typed, because the ArrayList collection is not strictly typed.

To insert a range of items anywhere in the ArrayList, use the InsertRange method, whose syntax is

aList.InsertRange(index, objects)

where index is the index of the ArrayList where the new elements will be inserted and objects is a collection with the elements to be inserted.

Finally, you can overwrite a range in the ArrayList with a new range, with the SetRange method. To overwrite the items in locations 5 through 9 in an ArrayList, use a few statements like the following:

Dim words() As String = {“Just”, “a”, “few”, “more”, “words”} aList.SetRange(5, words)

This code segment assumes that the aList collection contains at least 10 items, and it replaces five of them.

To remove an item, use the Remove method, whose syntax is:

aList.Remove(object)

The object argument is the value to be removed, and not an index value. The ArrayList allows you to remove items only by value. If the collection contains multiple instances of the same item, only the first instance of the object will be removed.

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

492 Chapter 11 STORING DATA IN COLLECTIONS

Notice that the Remove method compares values, not references. If the ArrayList contains a Rectangle object, you can search for this item by creating a new Rectangle variable and setting its properties to the properties of the Rectangle object you want to remove:

Dim R1 As New Rectangle(10, 10, 100, 100) Dim R2 As Rectangle

aList.Add(R1)

aList.Add(R2)

R2 = New Rectangle(10, 10, 100, 100) aList.Remove(R2)

If you execute these statements, they will add two identical rectangles to the aList ArrayList. The last statement will remove the first of the two rectangles.

If you attempt to remove an item that doesn’t exist, an exception will be thrown. You can always make sure that the item exists before attempting to remove it, by calling the Contains method, which returns True if the item exists in the ArrayList, False otherwise:

If aList.Contains(object) Then aList.Remove(object)

You can also remove items by specifying their order in the list with the RemoveAt method. This method accepts as argument the location of the item to remove, which must be less than the number of items currently in the list. The syntax of the RemoveAt method is

aList.RemoveAt(index)

To remove more than one consecutive item, use the RemoveRange method, whose syntax is

aList.RemoveRange(startIndex, count)

The startIndex argument is the index of the first item to be removed, and count is the number of items to be removed.

The following statements are examples of the methods that remove items from an ArrayList collection. The first two statements remove an item by value. The first statement removes an object, and the second removes a string item. The third statement removes the third item, and the last one removes the third through fifth items.

aList.Remove(Color.Red)

aList.Remove(“RichardM”)

aList.RemoveAt(2) aList.RemoveRange(2, 3)

If you execute all the statements in the order shown, the third statement may not remove the original collection’s third item. It will remove the third item of the collection as it has been rearranged after the execution of the first two statements. The same is true for the last statement. It will remove the elements at locations 2, 3, and 4, as they are arranged at the moment the statement is executed.

Copying Items

Besides adding and removing items, you can also extract selected items from an ArrayList with the GetRange method. The GetRange method extracts a number of consecutive elements from the ArrayList and stores them to a new ArrayList:

newList = ArrayList.GetRange(index, count)

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

THE ARRAYLIST COLLECTION 493

where index is the index of the first item to copy and count is the number of items to be copied. The GetRange method returns another ArrayList with the proper number of items.

The following statement copies three items from the aList ArrayList and inserts them at the beginning of the bList ArrayList. The three elements copied are the fourth through sixth elements in the original collection:

bList.InsertRange(0, aList.GetRange(3, 3))

The statements in Listing 11.4 populate the aList ArrayList with 10 strings. Then they copy elements 3 through 5 and add them to the start of the bList ArrayList. Then they copy elements 7 through 9 from the aList ArrayList and insert them in the bList ArrayList, right after the third element.

Listing 11.4: The GetRange and InsertRange Methods

Dim aList As New ArrayList() Dim names(10) As String

names(0) = “Item 0” : names(1) = “Item 1” names(2) = “Item 2” : names(3) = “Item 3” names(4) = “Item 4” : names(5) = “Item 5” names(6) = “Item 6” : names(7) = “Item 7” names(8) = “Item 8” : names(9) = “Item 9” aList.InsertRange(0, names)

ShowArrayList(aList)

Dim bList As New ArrayList() bList.InsertRange(0, aList.GetRange(3, 3)) ShowArrayList(aList)

bList.InsertRange(2, aList.GetRange(7, 3)) ShowArrayList(bList)

The ShowArrayList() procedure (Listing 11.5) displays the contents of the ArrayList in the Output window (the GetEnumerator method is discussed in detail later in this chapter).

Listing 11.5: The ShowArrayList() Subroutine

Sub ShowArrayList(ByVal List As Arraylist)

Dim AListEnum As IEnumerator

AListEnum = List.GetEnumerator

While AListEnum.MoveNext

Console.WriteLine(AListEnum.Current)

End While

Console.WriteLine()

End Sub

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

494 Chapter 11 STORING DATA IN COLLECTIONS

The output produced by Listing 11.5 is shown next in columns, so that you can compare the elements in the original ArrayList and the elements copied to the second ArrayList collection. The bList collection was populated with the items 3, 4, and 5 initially (the middle column in the following table). The second InsertRange statement inserted the items 7, 8, and 9 in front of the third element, which was pushed to the end of the list. The column bList (1) shows the contents of bList after the execution of the first InsertRange statement, and the column bList (2) shows the contents of bList after the execution of the second InsertRange statement.

aList

bList (1)

bList (2)

Item 0

Item 3

Item 3

Item 1

Item 4

Item 4

Item 2

Item 5

Item 7

Item 3

 

Item 8

Item 4

 

Item 9

Item 5

 

Item 5

Item 6

 

 

Item 7

 

 

Item 8

 

 

Item 9

 

 

The Repeat method fills an ArrayList with multiple instances of the same item, and its syntax is

newList = aList.Repeat(item, count)

This method returns a new ArrayList with count elements, all of them being identical to the item argument. To fill an ArrayList with the string “New Item”, use the following statement:

newList = System.ArrayList.Repeat(“New Item”, 10)

Another method of the ArrayList class is the Reverse method, which reverses the order of the elements in an ArrayList collection, or a portion of it, and its syntax is

newList = aList.Reverse()

or

newList = aList.Reverse(startIndex, endIndex)

The first form of the method reverses the entire collection; the second form reverses a section of the collection. Both methods return another ArrayList with the same elements as the original, only in reverse order.

Sorting ArrayLists

To sort the ArrayList, use the Sort method, which has three overloaded forms:

aList.Sort()

aList.Sort(comparer) aList.Sort(startIndex, endIndex, comparer)

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

THE ARRAYLIST COLLECTION 495

The ArrayList’s Sort method doesn’t require that you pass the name of the ArrayList to be sorted as argument. aList is a properly declared and initialized ArrayList object. The first form of the Sort method sorts the ArrayList alphabetically or numerically, depending on the data type of the objects stored in it. If the items are not all of the same type, an exception will be thrown. You’ll see how you can handle this exception shortly.

If the items stored in the ArrayList are of a data type other than the base data types, you must supply your own mechanism to compare the objects. The other two forms of the Sort method use a custom function for comparing items. Notice that there is no overloaded form of the Sort method that sorts a section of the ArrayList.

Note Despite their similarities, the Sort method of ArrayList collection is not as flexible as the Sort method of the Array class. For example, you can’t sort an ArrayList collection based on the values in another collection.

The Sort method will sort an ArrayList only if all the items are of the same type or if the items can be compared by the default comparer provided by a specific data type. The list may contain items of widely different types, in which case the Sort method will fail. To prevent a runtime exception, you must make sure that all items are of the same type. If you can’t ensure that all the items are of the same type, catch the possible error and handle it from within your code, as demonstrated in Listing 11.6.

Listing 11.6: Foolproof Sorting

Dim Sorted As Boolean = True

Try

aList.Sort()

Catch SortException As Exception

MsgBox(SortException.Message)

Sorted = False

End Try

If Sorted Then

{process sorted ArrayList }

Else

{process unsorted list } End If

The Sorted Boolean variable is initially set to True, because the Sort method will most likely succeed. If not, an exception will be thrown, in which case the code resets the Sorted variable to False and uses it later to distinguish between sorted and unsorted collections. For example, if the collection was sorted properly, you can call the BinarySearch method. If not, you can only use the IndexOf and LastIndexOf methods to locate an item.

The Sort method can’t even sort a collection of various numeric data types. If some of the objects are Doubles and some Integers or Decimals, the Sort method will fail. You must either make sure that all the items in the ArrayList are of the same type, or provide your own function for comparing the ArrayList’s items.

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

496 Chapter 11 STORING DATA IN COLLECTIONS

Searching ArrayLists

Like arrays, the ArrayList class exposes the IndexOf and LastIndexOf methods to search in an unsorted list and the BinarySearch method for sorted lists. If you need to know the location of an item, use the IndexOf and LastIndexOf methods, which accept as argument the object to be located and return an index:

aList.IndexOf(object)

Here, object is the item you’re searching.

The LastIndexOf method has the same syntax, but it starts scanning the array from its end and moves backward toward the beginning. The IndexOf and LastIndexOf methods are overloaded. The other two forms of the IndexOf method are:

aList.IndexOf(object, startIndex) aList.IndexOf(object, startIndex, length)

The two additional arguments determine where the search starts and ends. The two methods return the index of the item, if it belongs to the collection. If not, they return the value –1. Both ArrayLists and Arrays are searched in a linear fashion, from beginning to end (or from end to beginning in the case of the LastIndexOf method).

Tip The IndexOf and LastIndexOf methods perform case-sensitive searches, and they report exact matches only.

If the ArrayList is sorted, use the BinarySearch method, which accepts as argument the object to be located and returns its index in the collection:

aList.BinarySearch(object)

where object is the item you’re looking for. This form of the BinarySearch method can’t be used with data types that don’t provide their own comparer (i.e., base types like integers and strings). To use the BinarySearch method with an ArrayList of custom objects, you must provide your own comparer, which is the same as the one used with the Sort method to sort the collection.

There are two more forms of this method. To search for an item in an ArrayList with different data types, use the following form of the BinarySearch method:

aList.BinarySearch(object, comparer)

The first argument is the object you’re searching for, and the second is the name of an IComparer object.

Another form of the BinarySearch method allows you to search for an item in a section of the collection; its syntax is

aList.BinarySearch(startIndex, length, object, comparer)

The first argument is the index at which the search will begin, and the second argument is the length of the subrange. object and comparer are the same as with the second form of the method. For more information on the BinarySearch method, see the description of the BinarySearch method of the Array class. The two methods are identical, and they apply to sorted lists only.

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com