Basic Collections

The .NET Framework includes classes that compare to some of the core collections found in Java, but the overall support and flexibility fall short. This section covers the basic .NET collections, which are similar to their Java equivalents. We begin with coverage of arrays; .NET introduces some clever changes that allow arrays to be treated like collections.

Arrays

The most fundamental type of collection is the array. The use of arrays in .NET is similar to that in Java, with one significant enhancement: all arrays derive from the System.Array class. By deriving all arrays from the System.Array class, .NET provides useful functionality for array creation and manipulation. Although Java arrays are technically classed as objects, the language exposes methods only from the java.lang.Object class.

Predominantly, arrays are created, assigned, and accessed using the integral language support provided by C#. For example:

int[] x_arr = new int[10];
int[][] x_jagged = new int[2][];
int[,] x_multi = new int[2, 3];
int[] x_defined = new int[] {10, 20, 30};

More Info

Comprehensive coverage of the language support provided by C# for array creation and manipulation is in Chapter 5.

The remainder of this section focuses on the object properties of arrays and their use as a collection.

Arrays as Objects

All the array actions that are normally handled using language syntax are possible through the members of System.Array. For example, the following code fragments are functionally equivalent:

// Using language syntax
int[] x_arr = new int[2];
x_arr[0] = 10;
x_arr[1] = 20;
for (int i = 0; i < x_arr.Length; i++) {
    Console.WriteLine("Index {0}, Value {1}", i, x_arr[i]);
}

// Using System.Array members
Array x_arr = Array.CreateInstance(typeof(int), 2);
x_arr.SetValue(10, 0);
x_arr.SetValue(20, 1);
for (int i = 0; i < x_arr.Length; i++) {
    Console.WriteLine("Index {0}, Value {1}", i, x_arr.GetValue(i));
}

These examples demonstrate the object capabilities of .NET arrays. Bear in mind that while it is possible to use the System.Array class to handle all array features, there is no need to do so and the native support is recommended for most array operations.

The primary advantage of the System.Array class is that it implements ICollection, IList, and IEnumerable, which allow arrays to be treated as collections. In addition, there are some useful static methods in Array that support sorting and searching. This feature will not revolutionize programming, but it is clever, and we admire the forethought of the designers.

Table 9-3 summarizes the methods and properties available in the .NET System.Array class and identifies their Java equivalents. Because Java doesn’t include a class comparable to System.Array, the alternatives are all static methods from the java.util.Arrays and java.lang.System utility classes.

Table 9-3. Comparison Between Java and C# Array Methods

Java

Member

Description

N/A

Array.Rank

Returns the number of dimensions in the array.

<array>.length

Array.Length

Returns the number of elements in the array.

<array>[index].length

Array.GetLength()

Gets the number of elements in a specified array dimension.

N/A

Array.Clear()

Sets the elements of the array to the default value (which can be 0, false, or null, depending on the array type).

Arrays.binarySearch()

Array.BinarySearch()

Searches an array for a key value. Applied to one-dimensional arrays only.

System.arraycopy()

Array.Copy()

Copies a region of the array into another array. The .NET implementation will ensure that values are correctly boxed and typed.

System.arraycopy()

Array.CopyTo()

Copies all of the elements in a one-dimensional array to another one-dimensional array.

N/A

Array.CreateInstance()

Creates a new array. (See foregoing examples.)

N/A

Array.GetValue()

Array.SetValue()

Gets or sets the value of an array element. Equivalent of <array>[index] = value.

N/A

Array.IndexOf()

Array.LastIndexOf()

Finds the first (or last) index of a value in a one-dimensional array.

N/A

Array.Reverse()

Reverses the order of the elements in a one-dimensional array.

Arrays.Sort()

Array.Sort()

Sorts the elements in a one-dimensional array.

N/A

Array.GetEnumerator()

Returns an enumerator that can be used to step over the elements.

Hashtable

The System.Collections.Hashtable class is similar to the Java java.util.HashMap class. The only important difference is that key/value pairs are stored and accessed via an indexer. Here’s an example of how to set and get a Hashtable element:

Hashtable x_hash = new Hashtable();
x_hash["key"] = "value";
object x_value = x_hash["key"];

The .NET Hashtable also provides the Add method, which adds a new key/value pair to the element set only if the key does not already exist. If the key does exist, an exception will be thrown.

Table 9-4 contrasts the principal methods of the System.Collections.Hashtable and java.lang.HashMap classes.

Table 9-4. Comparison Between C#’s Hashtable and Java’s HashMap Classes

Java HashMap

.NET Hashtable

Comments

clear()

Clear( )

 

containsKey()

ContainsKey()

Contains()

Contains and ContainsKey are equivalent.

containsValue()

ContainsValue()

 

get()

<hashtable>[key]

Implemented via an indexer.

put()

<hashtable>[key] = value

Implemented via an indexer. Does not accept null as a key.

N/A

Add()

Adds a key/value pair, but only if the key does not already exist in the Hashtable.

putAll()

N/A

 

keySet()

Keys

Returns an ICollection of the keys.

values()

Values

Returns an ICollection of the values.

isEmpty()

Count == 0

 

size()

Count

 

remove()

Remove()

 

entrySet()

GetEnumerator()

Returns an IEnumerator that will return instances of Dictionary.Entry, broadly similar to Map.Entry.

N/A

IsFixedSize

Determines whether the Hashtable has a fixed number of elements.

N/A

IsReadOnly

Determines whether modification can be made to the collection.

N/A

IsSynchronized

Determines whether the Hashtable is synchronized.

N/A

Synchronized()

Returns the Hashtable in a thread-safe wrapper.

ArrayList

The .NET System.Collections.ArrayList is equivalent to java.util.ArrrayList. Like Hashtable, ArrayList implements an indexer used to get and set the value at a specific index. The ArrayList class implements the IList interface and provides the unusual static method Adapter, which makes the methods for binary searches and sorting available on any IList by wrapping the collection in an ArrayList instance. This is not as useful as it sounds because the operations aren’t optimized for the underlying structure of the list. Apart from the indexer and the adapter support, the Java and .NET classes are much the same. Table 9-5 compares the Java and C# ArrayList implementations.

Table 9-5. Comparison of the Java and C# ArrayList Implementations

Java ArrayList

.NET ArrayList

Comments

add()

Add()

 

add(int, Object)

Insert()

 

addAll()

AddRange()

Adds all of the elements of an ICollection (which includes arrays) to the end of the ArrayList.

addAll(int, Collection)

InsertRange()

 

clear()

Clear()

 

contains()

Contains()

 

ensureCapacity()

Capacity

.NET property, used to set or get the capacity of the ArrayList.

get()

<arraylist>[index]

 

indexOf()

IndexOf()

 

lastIndexOf()

LastIndexOf()

 

isEmpty()

Count == 0

 

remove()

RemoveAt()

 

removeRange()

RemoveRange()

 

set()

<arraylist>[index] = value

 

size()

Count

 

toArray()

CopyTo()

Copies the contents of the ArrayList (or a range) to a one-dimensional array.

trimToSize()

TrimToSize

 

N/A

IsFixedSize

Determines whether this is a fixed size ArrayList.

N/A

FixedSize()

Returns a wrapped ArrayList that allows elements to be modified but not to be added

N/A

IsReadOnly

Determines whether the collection allows changes to the ArrayList elements.

Collections. UnmodifiableList()

ReadOnly()

Returns an ArrayList that does not allow elements to be modified.

Collections.BinarySearch()

BinarySearch()

 

subList()

GetRange()

 

iterator()

GetEnumerator()

 

N/A

SetRange()

Sets a range of the ArrayList to the values contained in an ICollection.

Collections.sort()

Sort()

 

Queue

A queue is a first in, first out (FIFO) collection, in which objects are retrieved in the order they were added. This is useful for processing messages or events. Although Java doesn’t provide a class that enforces the FIFO constraint, we’ve seen examples of the LinkedList class being used to represent a queue. The problem with this approach is that LinkedList elements can be manipulated in ways contradictory to the queue model. Happily,.NET provides the System.Collections.Queue class, a concrete implementation of a queue that enforces the FIFO rule.

The queue implementation is based on a circular array, and objects are inserted at one end and removed from the other. As with the ArrayList class, if the number of elements exceeds the capacity of the queue, the underlying array is resized to provide more space.

Here’s a simple example demonstrating how to use the Queue class:

Queue x_queue = new Queue();
x_queue.Enqueue("first element");
x_queue.Enqueue("second element");
x_queue.Enqueue("third element");

object x_obj = x_queue.Dequeue();
Console.WriteLine("Dequeued: " + x_obj.ToString());
IEnumerator x_num = x_queue.GetEnumerator();
while (x_num.MoveNext()) {
    Console.WriteLine("Element: "
        + x_num.Current.ToString());
}

The results of this example follow:

Dequeued: first element
Element: second element
Element: third element

Elements are added to the Queue using the Enqueue method and are removed using Dequeue. The Queue class implements the IEnumerable interface and can be used in a foreach loop. In contrast with an ArrayList, it’s not possible to get an element by index. However, it’s possible to see what value is at the head of the queue by calling Peek. It can be determined that a value is contained in the Queue by calling the Contains method. The number of elements in the queue is available using the Count property.

Stack

Unlike a queue, a stack is a last in, first out (LIFO) collection, in which the most recently added element is the one that will be returned first. Java and .NET both provide stack implementations. The .NET stack class is System.Collections.Stack. Here’s an example using Stack:

Stack x_stack = new Stack();
x_stack.Push("first element");
x_stack.Push("second element");
x_stack.Push("third element");

object x_obj = x_stack.Pop();
Console.WriteLine("POPPED: " + x_obj.ToString());

IEnumerator x_num = x_stack.GetEnumerator();
while (x_num.MoveNext()) {
    Console.WriteLine("ELEMENT: " + x_num.Current.ToString());
}

The result of this example follows:

POPPED: third element
ELEMENT: second element
ELEMENT: first element

The Java java.net.Stack class has been around since Java 1.0 and is derived from the Vector class. This presents a potential misuse problem whereby a reference to a Stack can be cast to a Vector, allowing the underlying elements to be manipulated as a list. The .NET implementation isn’t derived from any other collection and can’t be misused in this manner.

Table 9-6 shows the mapping between the Java and .NET stack classes.

Table 9-6. Comparison Between the Java and C# Stack Implementations

Java Stack

.NET Stack

empty()

Count == 0

peek()

Peek()

pop()

Pop()

push()

Push()

search()

N/A

clear()

Clear()

contains()

Contains()

iterator()

GetEnumerator()

SortedList

The System.Collections.SortedList class is a cross between a Hashtable and an ArrayList. Two arrays are maintained, one for keys and one for values. The value array is used when a value is requested by index, like an ArrayList. When a value is requested by key, the index is obtained by searching the key array and then the matching value is obtained from the value array, which behaves like a Hashtable but requires more operations.

When a new item is added, the key array is re-sorted, and the value array is adjusted to reflect the changes. This is an unusual approach, and it can be seen that special support was added to the System.Array class to assist in the sort operations. (For example, look at the Sort(Array, Array) method as an example of this special support.) The closest analog in Java is the java.util.SortedSet interface and related concrete implementations.

In general, requesting values by key is slower with a SortedList than a Hashtable. However, the advantage of being able to request a value by index makes this class valuable for some problems. Here’s a simple example for this class:

SortedList x_list = new SortedList();
x_list["allen"] = "jones";
x_list["adam"]  = "freeman";
// get the first element
Console.WriteLine("First element: " + x_list.GetByIndex(0));
// get the index of the key "allen"
Console.WriteLine("Index of "allen": " +
    x_list.IndexOfKey("allen"));
// get the index of the value "freeman"
Console.WriteLine("Index of value "freeman": " +
    x_list.IndexOfValue("freeman"));

The output from this fragment is

First element: freeman
Index of "allen": 1
Index of value "freeman": 0

The sorting operations can be handled by using the CompareTo method of classes that implement IComparable or by an instance of IComparator.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset