Working with Collections


You've been using collections throughout this book to store objects. Many of the standard ASP.NET controls, such as DropDownList and DataGrid , use collections internally to store the items they display. In the following sections, you look at the properties and methods of the different types of collections in detail.

Most of the collection classes inhabit the System.Collections namespace, which includes several types of collections. Some of these collections are generally useful, whereas some were designed for more specialized functions.

I discuss three types of collections in these sections:

  • ArrayLists

  • HashTables

  • SortedLists

Using the ArrayList Collection

An ArrayList enables you to store lists of objects (any type of object, even other ArrayLists ). Using an ArrayList is similar to using an array, except that an ArrayList does not have any fixed upper bound. An ArrayList also has a number of useful properties and functions that it does not share with an array.

You can create a new ArrayList by using the following statement:

 
 colArrayList = New ArrayList() 

This statement creates an ArrayList that can initially store 16 objects. If you attempt to store more than 16 objects, the capacity of the ArrayList is automatically doubled . The capacity keeps doubling to handle the number of elements added.

If you know the number of elements that an ArrayList will store before you create the ArrayList , you can get the (ever so slight ) performance benefit by declaring the ArrayList with a particular starting capacity. For example, if you know that an ArrayList will be used to store 100 items, you can declare it like this:

 
 colArrayList = New ArrayList( 100 ) 

This ArrayList is declared to handle 100 elements. If you add a 101st element, the capacity of the ArrayList automatically doubles to 200.

You can determine the number of elements in an ArrayList at any time by using the Count property. You can determine the current capacity of an ArrayList at any time by using the Capacity property. For example, the following statements display the numbers and 16 :

 
 Dim colArrayList As ArrayList colArrayList = New ArrayList Response.Write( colArrayList.Count & "," & colArrayList.Capacity ) 

The numbers and 16 are displayed because they are the initial values of the Count and Capacity properties.

If you are working with a really huge ArrayList , you can trim its capacity back to its current size by using the TrimToSize method as follows :

 
 colArrayList.TrimToSize() 

The TrimToSize method changes the capacity of the ArrayList to match its current number of items.

Finally, if you want to clear all the objects out of an ArrayList and start over again, you can use the Clear method like this:

 
 colArrayList.Clear() 

The Clear method gets rid of all the current items in an ArrayList . However, it does not reset the capacity. To clear all the items and reset the capacity, you must call both the Clear and TrimToSize methods.

Adding Items to an ArrayList

You can add individual items to an ArrayList by using the Add method. For example, the following statement adds the string "Hello World!" to an ArrayList :

 
 colArrayList.Add( "Hello World!" ) 

Remember that an ArrayList can contain any type of object. So, you can add integers, TextBox controls, or any weird object that you discover in the .NET framework.

When you add an object to an ArrayList , it's added to the end as the last element. You can return the index of an item that you add to an ArrayList like this:

 
 intItemIndex = colArrayList.Add( "Hello World!" ) 

If this were the first item added to the ArrayList , intItemIndex would return ; if it were the second, intItemIndex would return 1 ; and so on.

If you need to add multiple objects to an ArrayList at once, you can use the AddRange method. For example, the following statement adds all the items in an ArrayList named colAnotherArrayList to an ArrayList named colArrayList :

 
 colArrayList.AddRange( colAnotherArrayList ) 

You also can add multiple duplicate items to an ArrayList by using the Repeat method:

 
 colArrayList = ArrayList.Repeat( "Hello World!", 100 ) 

The Repeat method returns an ArrayList that contains a value repeated a certain number of times. In this case, the ArrayList would contain 100 items with the value "Hello World!" .

If you need to insert an object into an ArrayList at a particular position, you can use the Insert method. For example, the following statement inserts the string "Hello World!" at the fourth index position:

 
 colArrayList.Insert( 4, "Hello World!" ) 

The InsertRange method also corresponds to the AddRange method. You can use the InsertRange method, as shown here, to add multiple objects starting at a certain position:

 
 colArrayList.InsertRange( 4, colAnotherArrayList ) 

This statement adds the contents of an ArrayList named colAnotherArrayList to an ArrayList named colArrayList starting at the fourth index position.

NOTE

You can use the AddRange and InsertRange methods to add other types of objects to an ArrayList as well. You can use these methods with any object that supports the ICollection interface.


You might be disappointed that you can add only single items to an ArrayList . The Add method accepts only one argument. However, this disappointment is not warranted. Remember that an ArrayList can contain any type of object. If you want to add multiple items to an ArrayList at a time, use a class with the ArrayList .

The page in Listing 24.1, for example, contains a class named Products . This class has both ProductName and Price properties.

Listing 24.1 MultiArrayList.aspx
 <Script Runat="Server"> Public Class Product   Public ProductName As String   Public Price As Decimal   Public Sub New( ProductName As String, Price As Decimal )     MyBase.New()     Me.ProductName = ProductName     Me.Price = Price   End Sub End Class Sub Page_Load   Dim colArrayList As ArrayList   colArrayList = New ArrayList   colArrayList.Add( New Product( "eggs", 2.10 ) )   colArrayList.Add( New Product( "milk", 3.24 ) )   dlstDataList.DataSource = colArrayList   dlstDataList.DataBind() End Sub </Script> <html> <head><title>MultiArrayList.aspx</title></head> <body> <asp:DataList   ID="dlstDataList"   Runat="Server"> <itemTemplate>   <%# Container.DataItem.ProductName %>   - <%# String.Format( "{0:c}", Container.DataItem.Price ) %> </itemTemplate> </asp:DataList> </body> </html> 

The C# version of this code can be found on the CD-ROM.

In the Page_Load subroutine in Listing 24.1, an ArrayList named colArrayList is declared. Two instances of the Product class are added to the ArrayList . Finally, the ArrayList is bound to a DataList control, and the two products are displayed.

Removing Items from an ArrayList

The most straightforward method of removing an item from an ArrayList is to use the Remove method. For example, the following statement removes the item "Hello World!" from an ArrayList :

 
 colArrayList.Remove( "Hello World!" ) 

If an ArrayList contains duplicate items, the first item is removed. Beware that the Remove method performs an exact comparison, so it is case sensitive. If you attempt to remove a nonexistent item, nothing horrible happens. The whole ArrayList is searched for the item, and the Remove method gives up without generating an error.

If you need to remove an ArrayList item with a certain index, you can use the RemoveAt method like this:

 
 colArrayList.RemoveAt( 4 ) 

This statement removes the item with an index of 4. If the ArrayList doesn't contain an item at index position 4, an error is generated.

If you want to remove a range of items in an ArrayList , use the RemoveRange method. For example, the following statement removes three items (items 2 through 4), starting at index position 2:

 
 colArrayList.RemoveRange( 2, 3 ) 

Finally, if you want to clear all the items from an ArrayList , use the Clear method like this:

 
 colArrayList.Clear() 

Remember to call the TrimToSize method after calling Clear if you want to reduce the capacity of the ArrayList to the minimum (16 items).

Iterating Through the Items in an ArrayList

If you need to loop through the contents of an ArrayList , displaying each item, you can use either a For...Each or For...Next loop.

The following For...Each loop, for example, displays all the elements in an ArrayList named colArrayList :

 
 Dim strItem As String For Each strItem in colArrayList   Response.Write( strItem ) Next 

You can do the same thing with a For...Next loop:

 
 Dim intCounter As Integer for intCounter = 0 To colArrayList.Count - 1   Response.Write( colArrayList( intCounter ) ) Next 

In both cases, you assume that the ArrayList contains strings. If the ArrayList contains items with different types of data or you are not sure about the type of data contained in the ArrayList , you can loop through it by using an Object variable like this:

 
 Dim objItem As Object For Each objItem in colArrayList   Response.Write( objItem.ToString ) Next 

An Object type can accept any type of value. So, regardless of whether an ArrayList contains integers, strings, classes, or whatever, you can assign the items to an Object type.

Sorting Items in an ArrayList

You can sort the items in an ArrayList by using the Sort method. For example, the page in Listing 24.2 sorts all the elements in an ArrayList named colShoppingList .

Listing 24.2 SortArrayList.aspx
 <% Dim colShoppingList As ArrayList Dim strItem As String colShoppingList = New ArrayList colShoppingList.Add( "eggs" ) colShoppingList.Add( "milk" ) colShoppingList.Add( "beer" ) colShoppingList.Sort For Each strItem in colShoppingList   Response.Write( "<li>" & strItem ) Next %> 

The C# version of this code can be found on the CD-ROM.

In Listing 24.2, three items are added to the ArrayList : eggs, milk, and beer. When the Sort method is called, the items are sorted in alphabetical order: beer, eggs, milk.

You reverse the order in which items in an ArrayList are sorted by calling the Reverse method. This method reverses the order of all the elements in an ArrayList . For example, the page in Listing 24.3 sorts a list of random numbers and reverses the results.

Listing 24.3 ReverseArrayList.aspx
 <% Dim colArrayList As ArrayList Dim objRanNumber As Random Dim intCounter As Integer Dim intItem As Integer colArrayList = New ArrayList objRanNumber = New Random For intCounter = 1 to 10   colArrayList.Add( objRanNumber.Next( 100 ) ) Next colArrayList.Sort colArrayList.Reverse For Each intItem in colArrayList   Response.Write( "<li>" & intItem.ToString() ) Next %> 

The C# version of this code can be found on the CD-ROM.

Ten random numbers are assigned to the ArrayList in this listing. Next, the ArrayList is sorted, and the elements are reversed by calling the Reverse method.

Searching for Items in an ArrayList

You could find an element in an ArrayList by looping through all its elements until a match is found. However, this is a notoriously slow search algorithm. If an ArrayList contains thousands of elements, then, potentially , thousands of elements must be checked before a match is found.

You can perform this type of slow, linear search on an ArrayList by using the Contains method. For example, the page in Listing 24.4 uses the Contains method to find the number 53 in an ArrayList .

Listing 24.4 ContainsArrayList.aspx
 <% Dim colArrayList As ArrayList Dim intCounter As Integer Dim objRanNumber As Random colArrayList = New ArrayList objRanNumber = New Random For intCounter = 1 to 1000   colArrayList.Add( objRanNumber.Next( 1000 ) ) Next If colArrayList.Contains( 53 ) Then   Response.Write( "Found 53!" ) Else   Response.Write( "Couldn't Find 53!" ) End If %> 

The C# version of this code can be found on the CD-ROM.

In Listing 24.4, 1,000 random numbers are added to the ArrayList . The Contains method determines whether the number 53 is contained in it.

Using the Contains method can be slow when you're working with large ArrayLists . Fortunately, an ArrayList supports binary searches.

If you want to perform a binary search, the ArrayList must be sorted. A binary search takes advantage of the fact that the elements in an array occur in a certain order so that a match can be found more quickly.

CAUTION

A binary search can return incorrect results if an ArrayList is not sorted.


The page in Listing 24.5 illustrates how you can use the BinarySearch method.

Listing 24.5 BinarySearchArrayList.aspx
 <% Dim colArrayList As ArrayList Dim objranNumber As Random Dim intCounter As Integer Dim intItemIndex As Integer colArrayList = New ArrayList objRanNumber = New Random For intCounter = 1 to 1000   colArrayList.Add( objRanNumber.Next( 1000 ) ) Next colArrayList.Sort() intItemIndex = colArrayList.BinarySearch( 53 ) If intItemIndex > 0 Then   Response.Write( "Found 53!" ) Else   Response.Write( "Couldn't Find 53!" ) End If %> 

The C# version of this code can be found on the CD-ROM.

If the BinarySearch method finds a match, it returns the index of the matched item in the ArrayList . Otherwise , it returns a negative number.

By default, the BinarySearch method performs a case-sensitive search. If you need to perform a search that is not case sensitive, call the BinarySearch method like this:

 
 intItemIndex = colArrayList.BinarySearch( "Smith", New CaseInsensitiveComparer ) 

This statement performs a binary search for Smith using an instance of CaseInsensitiveComparer . So, the statement matches both Smith and smith .

Using the HashTable Collection

A HashTable , like an ArrayList , can be used to store a collection of items. However, a HashTable , unlike an ArrayList , is used to store key and value pairs.

The key and value pairs can represent just about anything you desire . For example, you can use the key and value pairs to represent product codes and product names . Or the keys could represent page numbers, and the values could represent the contents of a page.

Each key in a HashTable must be unique. If you try to add two items with the same key, you receive an error. There's a good reason for this unique key requirement. You can look up a key very quickly in a HashTable because of the manner in which it stores its items.

Whenever you add an item to a HashTable , the HashTable calculates a hash code for the item's key. The HashTable internally sorts the hash codes using different buckets. By dividing the hash codes into different buckets, it can retrieve a key very quickly.

NOTE

A hash code is a shorthand representation of a value. For example, you can use a hash code to represent text that contains thousands of characters with a relatively small, fixed-length number.

Small differences in values result in different hash codes. So, two versions of the Declaration of Independence that differ in a single letter result in different hash codes.


You can create a new HashTable by using the following statement:

 
 colHashTable = New HashTable() 

This statement creates a new HashTable named colHashTable .

You also have the option, when creating a HashTable , of specifying its initial capacity. For example, if you know that the HashTable will be used to hold at least 100 items, you can declare the HashTable like this:

 
 colHashTable = New HashTable( 100 ) 

If you enter more than 100 items, the HashTable automatically expands to handle the greater number of items.

Finally, you can create a HashTable with a particular load factor. The load factor determines the number of buckets to use when sorting the hash codes for a HashTable. (It specifies the maximum ratio of items to buckets.) By default, a HashTable is initialized with a load factor of 1.0. However, you can use a lower value, as shown here, if you want to use more buckets and perform faster searches:

 
 colHashTable = New HashTable( 100, 0.1 ) 

This statement initializes the HashTable with a capacity of 100 items and a load factor of 0.1 (the minimum load factor). The advantage of a lower load factor is faster searches. The disadvantage of using a lower load factor is that it requires more memory.

Adding Items to a HashTable

You can add an item to a HashTable in two ways. First, you can use the Add method like this:

 
 colHashTable.Add( "WA", "Washington" ) 

This statement adds a new key with the value "WA" and a new item with the value "Washington" to the HashTable named colHashTable .

Alternatively, you can add a value to a HashTable like this:

 
 colHashTable( "WA" ) = "Washington" 

If the key "WA" doesn't already exist, it's added with the value. If the key already exists, it's assigned the new value.

Remember, you cannot add duplicate keys to a HashTable . So, the following two statements would result in an error:

 
 colHashTable.Add( "CA", "California" ) colHashTable.Add( "CA", "California" ) 

However, there is nothing wrong with adding two items with the same value. The following two statements would not generate an error:

 
 colHashTable.Add( "CA", "California" ) colHashTable.Add( "CALIF", "California" ) 
Removing Items from a HashTable

You use the Remove method to remove an item from a HashTable . For example, to remove an item with the key "WA" , you would use the following statement:

 
 colHashTable.Remove( "WA" ) 

Realize that the Remove method is, by default, case sensitive. So, this statement would not remove an item with the key "Wa" .

If you want to remove all the items in a HashTable , you can call the Clear method like this:

 
 colHashTable.Clear() 

This statement removes all the items in the HashTable named colHashTable .

Iterating Through the Items in a HashTable

Several methods can be used for displaying the items in a HashTable . You can use a For...Each loop like this, for example:

 
 Dim objItem As DictionaryEntry For each objItem in colHashTable   Response.Write( "<li>" & objItem.Key & "=" & objItem.Value ) Next 

This For...Each loop displays the key and value for each item in the HashTable named colHashTable . (Notice that each item in a HashTable is actually an instance of the DictionaryEntry class.)

You also can use a For...Each loop to iterate through the Keys collection of a HashTable like this:

 
 Dim strItem As String For Each strItem in colHashTable.Keys   Response.Write( "<li>" & strItem ) Next 

The Keys collection represents all the keys in a HashTable . I'm assuming that all the keys are strings. If the Keys collection contains items of another type, such as integers, you need to declare a variable with the appropriate type.

You also can loop through all the values in a HashTable by using the Values collection:

 
 Dim strItem As String For Each strItem in colHashTable.Values   Response.Write( "<li>" & strItem ) Next 

Again, I'm assuming that all the values are strings. If the items in the Values collection are a different type, you need to declare a variable with the appropriate type.

Searching for Items in a HashTable

The HashTable collection was designed to enable you to quickly look up a key and retrieve the key's associated value.

The simplest way to retrieve a certain value from a HashTable that has a certain key is to use the following:

 
 Response.Write( colHashTable( "WA" ) ) 

This statement displays the value for the "WA" key. (The comparison is case sensitive.)

If you simply want to check whether a certain key exists in a HashTable , you can use the Contains method like this:

 
 If colHashTable.Contains( "WA" ) Then   Response.Write( "Found WA!" ) Else   Response.Write( "Couldn't Find WA!" ) End If 

The Contains method returns True if the key exists and False otherwise. (Again, the Contains method is case sensitive.)

NOTE

If you want to perform comparisons that are not case sensitive with a HashTable , you need to declare it like this:

 
 colHashTable = New HashTable( _   New CaseInsensitiveHashCodeProvider, _   New CaseInsensitiveComparer ) 

This statement initializes the HashTable with a hash code provider that enables hash code comparisons that are not case sensitive. It also uses the CaseInsensitiveComparer to compare values.


HashTables are very good at finding keys. They are slower at finding values, however. You can find a particular value by using the ContainsValue method:

 
 If colHashTable.ContainsValue( "Washington" ) Then   Response.Write( "Found Washington!" ) Else   Response.Write( "Couldn't Find Washington!" ) End If 

The ContainsValue method must perform a linear search on the elements of the HashTable . So, the more elements in a HashTable , the slower the search.

Using the SortedList Collection

HashTables are great for quickly looking up a key and finding an associated value. However, they are not useful for displaying items in a certain order. You have no control over the order in which a HashTable internally represents its items.

A SortedList collection, on the other hand, enables you to control exactly how items are sorted. You can create a new instance of the SortedList collection like this:

 
 colSortedList = New SortedList() 

You also have the option of declaring a SortedList with an initial capacity like this:

 
 colSortedList = New SortedList( 100 ) 

This statement creates a new SortedList with an initial capacity of 100 elements. If you add more than 100 elements, the SortedList automatically doubles in size to handle the new elements.

Adding Items to a SortedList

Like a HashTable , a SortedList contains key and value pairs. You can add a new key and value pair to a SortedList by using the Add method like this:

 
 colSortedList.Add( "Bob", "(415) 455-9090" ) 

This statement adds a new key, "Bob" , and a new value, "(415) 455-9090" , to a SortedList named colSortedList .

Alternatively, you can add a new item to a SortedList like this:

 
 colSortedList( "Bob" ) = "(415) 455-9090" 

A SortedList cannot contain duplicate keys. So, if you try to execute this statement twice, an error is generated. There is nothing wrong, however, with adding duplicate values to a SortedList .

Whenever you add new items to a SortedList , they are automatically added in the right order. For example, imagine that you add the following three items:

 
 colSortedList.Add( "eggs", 2.39 ) colSortedList.Add( "beer", 8.16  ) colSortedList.Add( "milk", 4.87 ) 

The SortedList automatically rearranges the items in the following order: beer, eggs, milk. Notice that the items are sorted in order of the keys, and not the values.

Removing Items from a SortedList

You can remove an item from a SortedList by using its key or index position to refer to the item. For example, the following statement removes an item with the key "eggs" :

 
 colSortedList.Remove( "eggs" ) 

You also can remove an item according to its index position in the list by using the RemoveAt method like this:

 
 colSortedList.RemoveAt( 1 ) 

Remember, when you're using the RemoveAt method, the items in a SortedList are automatically ordered. So, an item's index position has nothing to do with the order in which you added the item.

If you want to clear away all the items in a SortedList , you can use the Clear method like this:

 
 colSortedList.Clear() 

This statement removes all the items from a SortedList named colSortedList .

Clearing a SortedList does not automatically reduce the capacity of the list. To reduce the capacity of a SortedList to its initial capacity (16 items), you need to call the TrimToSize method after calling the Clear method like this:

 
 colSortedList.Clear() colSortedList.TrimToSize() 
Iterating Through the Items in a SortedList

Several methods can be used to loop through the contents of a SortedList . For example, you can display all the elements by using a For...Each loop like this:

 
 Dim objItem As DictionaryEntry For each objItem in colSortedList   Response.Write( "<li>" & objItem.Key & "=" & objItem.Value ) Next 

Notice that each entry in a SortedList is actually an instance of the DictionaryEntry class. The Key and Value properties are used to display the key and value for each item in the SortedList .

You also can use the Keys property to display each key in a SortedList like this:

 
 Dim strItem As String For each strItem in colSortedList.Keys   Response.Write( "<li>" & strItem ) Next 

A Value property also enables you to display all the values in a SortedList :

 
 Dim strItem As String For each strItem in colSortedList.Values   Response.Write( "<li>" & strItem ) Next 

I'm assuming here that the SortedList contains strings. You need to use the correct data type for the items contained in the SortedList (for example, Integer , Decimal , or Object ).

Finding Items in a SortedList

The most straightforward way of displaying the value of an item with a certain key in a SortedList is to use a statement like this:

 
 Response.Write( colSortedList( "eggs" ) ) 

If the SortedList contains a list of grocery store items and their prices, this statement displays the price of eggs.

If you want to check whether a SortedList contains a particular key, you can use the Contains method like this:

 
 If colSortedList.Contains( "eggs" ) Then   Response.Write( "We sell eggs!" ) Else   Response.Write( "Nope, no eggs!" ) End If 

The Contains method returns True if the key exists and False otherwise.

NOTE

By default, a SortedList is case sensitive. So, the key "eggs" is treated differently than the key "eGGs" . If you want to perform comparisons that are not case sensitive, you need to initialize the SortedList collection like this:

 
 colSortedList = New SortedList( New CaseInsensitiveComparer ) 

This statement initializes the SortedList with CaseInsensitiveComparer .


The Contains method uses a fast binary search to find a matching key. The process of finding a matching value is slower because a linear search must be performed. You can check whether a SortedList contains a particular value by using the ContainsValue method as follows:

 
 If colSortedList.ContainsValue( 2.39 ) Then   Response.Write( "Found It!" ) Else   Response.Write( "Couldn't Find It!" ) End If 

Here, the ContainsValue method finds an item with the value 2.39 . If an item is found, the ContainsValue method returns True ; otherwise, it returns False .



ASP.NET Unleashed
ASP.NET 4 Unleashed
ISBN: 0672331128
EAN: 2147483647
Year: 2003
Pages: 263

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net