Книга: C# 4.0: полное руководство

Классы необобщенных коллекций

Классы необобщенных коллекций

А теперь, когда представлены интерфейсы необобщенных коллекций, можно перейти к рассмотрению стандартных классов, в которых они реализуются. Ниже приведены классы необобщенных коллекций, за исключением коллекции типа BitArray, рассматриваемой далее в этой главе.

Класс - Описание

ArrayList - Определяет динамический массив, т.е. такой массив, который может при необходимости увеличивать свой размер

Hashtable - Определяет хеш-таблицу для пар “ключ-значение”

Queue - Определяет очередь, или список, действующий по принципу “первым пришел — первым обслужен”

SortedList - Определяет отсортированный список пар “ключ-значение”

Stack - Определяет стек, или список, действующий по принципу “первым пришел — последним обслужен”

Каждый из этих классов коллекций подробно рассматривается и демонстрируется далее на конкретных примерах.

Класс Arгaylist

В классе ArrayList поддерживаются динамические массивы, расширяющиеся и сокращающиеся по мере необходимости. В языке C# стандартные массивы имеют фиксированную длину, которая не может изменяться во время выполнения программы. Это означает, что количество элементов в массиве нужно знать заранее. Но иногда требуемая конкретная длина массива остается неизвестной до самого момента выполнения программы. Именно для таких ситуаций и предназначен класс ArrayList. В классе ArrayList определяется массив переменной длины, который состоит из ссылок на объекты и может динамически увеличивать и уменьшать свой размер. Массив типа ArrayList создается с первоначальным размером. Если этот размер превышается, то массив автоматически расширяется. А при удалении объектов из такого массива он автоматически сокращается. Коллекции класса ArrayList широко применяются в практике программирования на С#. Именно поэтому они рассматриваются здесь подробно. Но многие способы применения коллекций класса ArrayList распространяются и на другие коллекции, в том числе и на обобщенные.

В классе ArrayList реализуются интерфейсы ICollection, IList, IEnumerable и ICloneable. Ниже приведены конструкторы класса ArrayList.

public ArrayList()
public ArrayList(ICollection с)
public ArrayList(int capacity)

Первый конструктор создает пустую коллекцию класса ArrayList с нулевой первоначальной емкостью. Второй конструктор создает коллекцию типа ArrayList с количеством инициализируемых элементов, которое определяется параметром с и равно первоначальной емкости массива. Третий конструктор создает коллекцию, имеющую указанную первоначальную емкость, определяемую параметром capacity. В данном случае емкость обозначает размер базового массива, используемого для хранения элементов коллекции. Емкость коллекции типа ArrayList может увеличиваться автоматически по мере добавления в нее элементов.

В классе ArrayList определяется ряд собственных методов, помимо тех, что уже объявлены в интерфейсах, которые в нем реализуются. Некоторые из наиболее часто используемых методов класса ArrayList перечислены в табл. 25.4. Коллекцию класса ArrayList можно отсортировать, вызвав метод Sort(). В этом случае поиск в отсортированной коллекции с помощью метода BinarySearch() становится еще более эффективным. Содержимое коллекции типа ArrayList можно также обратить, вызвав метод Reverse().

Таблица 25.4. Наиболее часто используемые методы, определенные в классе ArrayList

Метод - Описание

public virtual void AddRange(Icollection с) public virtual int BinarySearch(object value) - Добавляет элементы из коллекции с в конец вызывающей коллекции типа ArrayList Выполняет поиск в вызывающей коллекции значения value. Возвращает индекс найденного элемента. Если искомое значение не найдено, возвращает отрицательное значение. Вызывающий список должен быть отсортирован

public virtual int BinarySearcii (object value,-Icomparer comparer) - Выполняет поиск в вызывающей коллекции значения value, используя для сравнения способ, определяемый параметром comparer. Возвращает индекс совпавше го элемента. Если искомое значение не найдено, возвращает отрицательное значение. Вызывающий список должен быть отсортирован

public virtual int BinarySearch(int index, int count,object value, IComparer comparer) - Выполняет поиск в вызывающей коллекции значения value, используя для сравнения способ, определяемый параметром comparer. Поиск начинается с элемента, указываемого по индексу index, и включает количество элементов, определяемых параметром count. Метод возвращает индекс совпавшего элемента. Если искомое значение не найдено, метод возвращает отрицательное значение. Вызывающий список должен быть отсортирован

public virtual void CopyTo(Array array) - Копирует содержимое вызывающей коллекции в массив array, который должен быть одномерным и совместимым по типу с элементами коллекции

public virtual void CopyTo(Array array,int arraylndex) - Копирует содержимое вызывающей коллекции в массив array, начиная с элемента, указываемого по индексу arraylndex. Целевой массив должен быть одномерным и совместимым по типу с элементами коллекции

public virtual void CopyTo(int index,Array array,int arraylndex, int count) - Копирует часть вызывающей коллекции, начиная с элемента, указываемого по индексу index, и включая количество элементов, определяемых параметром count, в массив array, начиная с элемента, указываемого по индексу arraylndex. Целевой массив должен быть одномерным и совместимым по типу с элементами коллекции

public static ArrayList FixedSize(ArrayList list) - Заключает коллекцию list в оболочку типа ArrayList с фиксированным размером и возвращает результат

public virtual ArrayList GetRange(int index,int count) - Возвращает часть вызывающей коллекции типа ArrayList. Часть возвращаемой коллекции начинается с элемента, указываемого по индексу index, и включает количество элементов, определяемое параметром count. Возвращаемый объект ссылается на те же элементы, что и вызывающий объект

public virtual int IndexOf(object value) - Возвращает индекс первого вхождения объекта value в вызывающей коллекции. Если искомый объект не обнаружен, возвращает значение -1

public virtual void InsertRange(int index, ICollection c) - Вставляет элементы коллекции с в вызывающую коллекцию, начиная с элемента, указываемого по индексу index

public virtual int LastlndexOf(object value) - Возвращает индекс последнего вхождения объекта value в вызывающей коллекции. Если искомый объект не обнаружен, метод возвращает значение -1

public static ArrayList Readonly(ArrayList list) - Заключает коллекцию list в оболочку типа ArrayList, доступную только для чтения, и возвращает результат

public virtual void RemoveRange(int index, int count) - Удаляет часть вызывающей коллекции, начиная с элемента, указываемого по индексу index, и включая количество элементов, определяемое параметром count

public virtual void Reverse() - Располагает элементы вызывающей коллекции в обратном порядке

public virtual void Reverse(int index,int count) - Располагает в обратном порядке часть вызывающей коллекции, начиная с элемента, указываемого по индексу index, и включая количество элементов, определяемое параметром count

public virtual void SetRange(int index, ICollection c) - Заменяет часть вызывающей коллекции, начиная с элемента, указываемого по индексу index, элементами коллекции с

public virtual void Sort() - Сортирует вызывающую коллекцию по нарастающей

public virtual void  Sort(Icomparer comparer) - Сортирует вызывающую коллекцию, используя для сравнения способ, определяемый параметром comparer. Если параметр comparer имеет пустое значение, то для сравнения используется способ, выбираемый по умолчанию

public virtual void Sort(int index,int count,Icomparer comparer) - Сортирует вызывающую коллекцию, используя для сравнения способ, определяемый параметром comparer. Сортировка начинается с элемента, указываемого по индексу index, и включает количество элементов, определяемых параметром count. Если параметр comparer имеет пустое значение, то для сравнения используется способ, выбираемый по умолчанию

public static ArrayList Synchronized(ArrayList list) - Возвращает синхронизированный вариант коллекции типа ArrayList, передаваемой в качестве параметра list

public virtual object[]  ToArray() - Возвращает массив, содержащий копии элементов вызывающего объекта

public virtual Array ToArray(Type type) - Возвращает массив, содержащий копии элементов вызывающего объекта. Тип элементов этого массива определяется параметром type

public virtual void TrimToSize() - Устанавливает значение свойства Capacity равным значению свойства Count

В классе ArrayList поддерживается также ряд методов, оперирующих элементами коллекции в заданных пределах. Так, в одну коллекцию типа ArrayList можно вставить другую коллекцию, вызвав метод InsertRange(). Для удаления из коллекции элементов в заданных пределах достаточно вызвать метод RemoveRange(). А для перезаписи элементов коллекции типа ArrayList в заданных пределах элементами из другой коллекции служит метод SetRange(). И наконец, элементы коллекции можно сортировать или искать в заданных пределах, а не во всей коллекции.

По умолчанию коллекция типа ArrayList не синхронизирована. Для получения синхронизированной оболочки, в которую заключается коллекция, вызывается метод Synchronized().

В классе ArrayList имеется также приведенное ниже свойство Capacity, помимо свойств, определенных в интерфейсах, которые в нем реализуются.

public virtual int Capacity { get; set; }

Свойство Capacity позволяет получать и устанавливать емкость вызывающей коллекции типа ArrayList. Емкость обозначает количество элементов, которые может содержать коллекция типа ArrayList до ее вынужденного расширения. Как упоминалось выше, коллекция типа ArrayList расширяется автоматически, и поэтому задавать ее емкость вручную необязательно. Но из соображений эффективности это иногда можно сделать, если количество элементов коллекции известно заранее. Благодаря этому исключаются издержки на выделение дополнительной памяти.

С другой стороны, если требуется сократить размер базового массива коллекции типа ArrayList, то для этой цели достаточно установить меньшее значение свойства Capacity. Но это значение не должно быть меньше значения свойства Count. Напомним, что свойство Count определено в интерфейсе ICollection и содержит количество объектов, хранящихся в коллекции на данный момент. Всякая попытка установить значение свойства Capacity меньше значения свойства Count приводит к генерированию исключения ArgumentOutOfRangeException. Поэтому для получения такого количества элементов коллекции типа ArrayList, которое содержится в ней на данный момент, следует установить значение свойства Capacity равным значению свойства Count. Для этой цели можно также вызвать метод TrimToSize().

В приведенном ниже примере программы демонстрируется применение класса ArrayList. В ней сначала создается коллекция типа ArrayList, а затем в эту коллекцию вводятся символы, после чего содержимое коллекции отображается. Некоторые элементы затем удаляются из коллекции, и ее содержимое отображается вновь. После этого в коллекцию вводятся дополнительные элементы, что вынуждает увеличить ее емкость. И наконец, содержимое элементов коллекции изменяется.

// Продемонстрировать применение класса ArrayList.
using System;
using System.Collections;
class ArrayListDemo {
  static void Main() {
    // Создать коллекцию в виде динамического массива.
    ArrayList al = new ArrayList();
    Console.WriteLine("Исходное количество элементов: " + al.Count);
    Console.WriteLine();
    Console.WriteLine("Добавить 6 элементов");
    // Добавить элементы в динамический массив.
    al.Add('С');
    al.Add('А');
    al.Add('E');
    al.Add('В');
    al.Add('D');
    al.Add('F') ;
    Console.WriteLine("Количество элементов: " + al.Count);
    // Отобразить содержимое динамического массива,
    // используя индексирование массива.
    Console.Write("Текущее содержимое: ");
    for(int i=0; i < al.Count; i++)
      Console.Write (al[i] + " ");
    Console.WriteLine("n");
    Console.WriteLine("Удалить 2 элемента");
    // Удалить элементы из динамического массива,
    al.Remove('F');
    al.Remove('A');
    Console.WriteLine("Количество элементов: " + al.Count);
    // Отобразить содержимое динамического массива, используя цикл foreach.
    Console.Write("Содержимое: ");
    foreach(char c in al)
      Console.Write(c + " ");
    Console.WriteLine("n");
    Console.WriteLine("Добавить еще 20 элементов");
    // Добавить количество элементов, достаточное для
    // принудительного расширения массива,
    for (int i=0; i < 20; i++)
      al.Add((char)('a' + i));
    Console.WriteLine("Текущая емкость: " + al.Capacity);
    Console.WriteLine("Количество элементов после добавления 20 новых: " + al.Count);
    Console.Write("Содержимое: ");
    foreach(char c in al)
      Console.Write(c + " ");
    Console.WriteLine("n");
    // Изменить содержимое динамического массива,
    // используя индексирование массива.
    Console.WriteLine("Изменить три первых элемента");
    al[0] = 'X';
    al[1] = 'Y';
    al[2] = 'Z';
    Console.Write("Содержимое: ");
    foreach(char c in al)
      Console.Write (c + " ");
    Console.WriteLine();
  }
}

Вот к какому результату приводит выполнение этой программы.

Исходное количество элементов: 0
Добавить 6 элементов
Количество элементов: 6
Текущее содержимое: С А E В D F
Удалить 2 элемента
Количество элементов: 5
Содержимое: С А E В D
Добавить еще 20 элементов
Текущая емкость: 32
Количество элементов после добавления 20 новых: 25
Содержимое: С А E В D a b c d e f g h i j k l m n o p q r s t
Изменить три первых элемента
Содержимое: X Y Z В D a b c d e f g h i j k l m n o p q r s t
Для продолжения нажмите любую клавишу . . .

Сортировка и поиск в коллекции типа ArrayList

Коллекцию типа ArrayList можно отсортировать с помощью метода Sort(). В этом случае поиск в отсортированной коллекции с помощью метода BinarySearch() становится еще более эффективным. Применение обоих методов демонстрируется в приведенном ниже примере программы.

// Отсортировать коллекцию типа ArrayList и осуществить в ней поиск.
using System;
using System.Collections;
class SortSearchDemo {
  static void Main() {
    // Создать коллекцию в виде динамического массива.
    ArrayList al = new ArrayList();
    // Добавить элементы в динамический массив.
    al.Add(55);
    al.Add(43) ;
    al.Add(-4);
    al.Add(88);
    al.Add(3);
    al.Add(19) ;
    Console.Write("Исходное содержимое: ");
    foreach(int i in al)
      Console.Write (i + " ");
    Console.WriteLine ("n");
    // Отсортировать динамический массив,
    al.Sort();
    // Отобразить содержимое динамического массива, используя цикл foreach.
    Console.Write ("Содержимое после сортировки: ");
    foreach (int i in al)
      Console.Write (i + " ");
    Console.WriteLine ("n");
    Console.WriteLine("Индекс элемента 43: " + al.BinarySearch (43));

  }

}

Ниже приведен результат выполнения этой программы.

Исходное содержимое: 55 43 -4 88 3 19
Содержимое после сортировки: -4 3 19 43 55 88
Индекс элемента 43: 3

В одной и той же коллекции типа ArrayList могут храниться объекты любого типа. Тем не менее во время сортировки и поиска в ней эти объекты приходится сравнивать. Так, если бы список объектов в приведенном выше примере программы содержал символьную строку, то их сравнение привело бы к исключительной ситуации. Впрочем, для сравнения символьных строк и целых чисел можно создать специальные методы. О таких методах сравнения речь пойдет далее в этой главе.

Получение массива из коллекции типа ArrayList

В работе с коллекцией типа ArrayList иногда требуется получить из ее содержимого обычный массив. Этой цели служит метод ТоАггау(). Для преобразования коллекции в массив имеется несколько причин. Две из них таковы: потребность в ускорении обработки при выполнении некоторых операций и необходимость передавать массив методу, который не перегружается, чтобы принять коллекцию. Но независимо от конкретной причины коллекция типа ArrayList преобразуется в обычный массив довольно просто, как показано в приведенном ниже примере программы.

// Преобразовать коллекцию типа ArrayList в обычный массив.
using System;
using System.Collections;
class ArrayListToArray {
  static void Main() {
    ArrayList al = new ArrayList();
    // Добавить элементы в динамический массив,
    al.Add(1);
    al.Add(2);
    al.Add(3);
    al.Add(4) ;
    Console.Write("Содержимое: ");
    foreach(int i in al)
      Console.Write(i + " ");
    Console.WriteLine();
    int[] ia = (int[])al.ToArray(typeof(int));
    int sum = 0;
    // Просуммировать элементы массива,
    for(int i=0; i < ia.Length; i++) sum += ia[i];
    Console.WriteLine("Сумма равна: " + sum);
  }
}

Эта программа дает следующий результат.

Содержимое: 1 2 3 4
Сумма равна: 10

В начале этой программы создается коллекция целых чисел. Затем в ней вызывается метод ToArray() с указанием типа int получаемого массива. В итоге создается целочисленный массив. Но поскольку Array является типом, возвращаемым методом ToArray(), то содержимое получаемого в итоге массива должно быть приведено к типу int[]. (Напомним, что Array является базовым типом для всех массивов в С#.) И наконец, значения всех элементов массива суммируются.

Класс Hashtable

Класс Hashtable предназначен для создания коллекции, в которой для хранения ее элементов служит хеш-таблица. Как должно быть известно большинству читателей, информация сохраняется в хеш-таблице с помощью механизма, называемого хешированием. При хешировании для определения уникального значения, называемого хеш-кодом, используется информационное содержимое специального ключа. Полученный в итоге хеш-код служит в качестве индекса, по которому в таблице хранятся искомые данные, соответствующие заданному ключу. Преобразование ключа в хеш-код выполняется автоматически, и поэтому сам хеш-код вообще недоступен пользователю. Преимущество хеширования заключается в том, что оно обеспечивает постоянство времени выполнения операций поиска, извлечения и установки значений независимо от величины массивов данных. В классе Hashtable реализуются интерфейсы IDictionary, ICollection, IEnumerable, ISerializable, IDeserializationCallback и ICloneable.

В классе Hashtable определено немало конструкторов. Ниже приведены наиболее часто используемые конструкторы этого класса.

public Hashtable()
public Hashtable(IDictionary d)
public Hashtable(int capacity)
public Hashtable(int capacity, float loadFactor)

В первой форме создается создаваемый по умолчанию объект класса Hashtable. Во второй форме создаваемый объект типа Hashtable инициализируется элементами из коллекции d. В третьей форме создаваемый объект типа Hashtable инициализируется, учитывая емкость коллекции, задаваемую параметром capacity. И в четвертой форме создаваемый объект типа Hashtable инициализируется, учитывая заданную емкость capacity и коэффициент заполнения loadFactor. Коэффициент заполнения, иногда еще называемый коэффициентом загрузки, должен находиться в пределах от 0,1 до 1,0. Он определяет степень заполнения хеш-таблицы до увеличения ее размера. В частности, таблица расширяется, если количество элементов оказывается больше емкости таблицы, умноженной на коэффициент заполнения. В тех конструкторах, которые не принимают коэффициент заполнения в качестве параметра, этот коэффициент по умолчанию выбирается равным 1,0.

В классе Hashtable определяется ряд собственных методов, помимо тех, что уже объявлены в интерфейсах, которые в нем реализуются. Некоторые из наиболее часто используемых методов этого класса приведены в табл. 25.5. В частности, для того чтобы определить, содержится ли ключ в коллекции типа Hashtable, вызывается метод ContainsKey(). А для того чтобы выяснить, хранится ли в такой коллекции конкретное значение, вызывается метод ContainsValue(). Для перечисления содержимого коллекции типа Hashtable служит метод GetEnumerator(), возвращающий объект типа IDictionaryEnumerator. Напомним, что IDictionaryEnumerator — это перечислитель, используемый для перечисления содержимого коллекции, в которой хранятся пары "ключ-значение".

Таблица 25.5. Наиболее часто используемые методы, определенные в классе Hashtable

Метод - Описание

public virtual bool ContainsKey(object key) - Возвращает логическое значение true, если в вызывающей коллекции типа Hashtable содержится ключ key, а иначе — логическое значение false

public virtual bool ContainsValue(object value) - Возвращает логическое значение true, если в вызывающей коллекции типа Hashtable содержится значение value, а иначе — логическое значение false

public virtual IDictionaryEnumerator GetEnumerator() - Возвращает для вызывающей коллекции типа Hashtable перечислитель типа IDictionaryEnumerator

public static Hashtable Synchronized(Hashtable table) -  Возвращает синхронизированный вариант коллекции типа Hashtable, передаваемой в качестве параметра table

В классе Hashtable доступны также открытые свойства, определенные в тех интерфейсах, которые в нем реализуются. Особая роль принадлежит двум свойствам, Keys и Values, поскольку с их помощью можно получить ключи или значения из коллекции типа Hashtable. Эти свойства определяются в интерфейсе IDictionary следующим образом.

public virtual ICollection Keys { get; }
public virtual ICollection Values { get; }

В классе Hashtable не поддерживаются упорядоченные коллекции, и поэтому ключи или значения получаются из коллекции в произвольном порядке. Кроме того, в классе Hashtable имеется защищенное свойство EqualityComparer. А два других свойства, hcp и comparer, считаются устаревшими.

Пары "ключ-значение" сохраняются в коллекции типа Hashtable в форме структуры типа DictionaryEntry, но чаще всего это делается без прямого вмешательства со стороны пользователя, поскольку свойства и методы оперируют ключами и значениями по отдельности. Если, например, в коллекцию типа Hashtable добавляется элемент, то для этой цели вызывается метод Add(), принимающий два аргумента: ключ и значение.

Нужно, однако, иметь в виду, что сохранение порядка следования элементов в коллекции типа Hashtable не гарантируется. Дело в том, что процесс хеширования оказывается, как правило, непригодным для создания отсортированных таблиц.

Ниже приведен пример программы, в которой демонстрируется применение класса Hashtable.

// Продемонстрировать применение класса Hashtable.
using System;
using System.Collections;
class HashtableDemo {
  static void Main() {
    // Создать хеш-таблицу.
    Hashtable ht = new Hashtable();
    // Добавить элементы в таблицу.
    ht.Add("здание", "жилое помещение");
    ht.Add("автомашина", "транспортное средство");
    ht.Add("книга", "набор печатных слов");
    ht.Add("яблоко", "съедобный плод");
    // Добавить элементы с помощью индексатора,
    ht["трактор"] = "сельскохозяйственная машина";
    // Получить коллекцию ключей.
    ICollection с = ht.Keys;
    // Использовать ключи для получения значений,
    foreach(string str in с)
      Console.WriteLine(str + ": " + ht[str]);
  }
}

Выполнение этой программы приводит к следующему результату.

здание: жилое помещение
книга: набор печатных слов
трактор: сельскохозяйственная машина
автомашина: транспортное средство
яблоко: съедобный плод

Как следует из приведенного выше результата, пары "ключ-значение" сохраняются в произвольном порядке. Обратите внимание на то, как получено и отображено содержимое хеш-таблицы ht. Сначала была получена коллекция ключей с помощью свойства Keys. Затем каждый ключ был использован для индексирования хеш-таблицы ht с целью извлечь из нее значение, соответствующее заданному ключу. Напомним, что в качестве индекса в данном случае использовался индексатор, определенный в интерфейсе IDictionary и реализованный в классе Hashtable.

Класс SortedList

Класс SortedList предназначен для создания коллекции, в которой пары "ключ-значение" хранятся в порядке, отсортированном по значению ключей. В классе SortedList реализуются интерфейсы IDictionary, ICollection, IEnumerable и ICloneable.

В классе SortedList определено несколько конструкторов, включая следующие.

public SortedList()
public SortedList(IDictionary d)
public SortedList(int initialCapacity)
public SortedList(IComparer comparer)

В первом конструкторе создается пустая коллекция, первоначальная емкость которой равна нулю. Во втором конструкторе создается пустая коллекция типа SortedList, которая инициализируется элементами из коллекции d. Ее первоначальная емкость равна количеству указанных элементов. В третьем конструкторе создается пустая коллекция типа SortedList, первоначальный размер которой определяет емкость, задаваемая параметром initialCapacity. Эта емкость соответствует размеру базового массива, используемого для хранения элементов коллекции. И в четвертой форме конструктора с помощью параметра сотпрагег указывается способ, используемый для сравнения объектов по списку. В этой форме создается пустая коллекция, первоначальная емкость которой равна нулю.

При добавлении новых элементов в список емкость коллекции типа SortedList увеличивается автоматически по мере надобности. Так, если текущая емкость коллекции превышается, то она соответственно увеличивается. Преимущество указания емкости коллекции типа SortedList при ее создании заключается в снижении или полном исключении издержек на изменение размера коллекции. Разумеется, указывать емкость коллекции целесообразно лишь в том случае, если заранее известно, сколько элементов требуется хранить в ней.

В классе SortedList определяется ряд собственных методов, помимо тех, что уже объявлены в интерфейсах, которые в нем реализуются. Некоторые из наиболее часто используемых методов этого класса перечислены в табл. 25.6. Так, если требуется определить, содержится ли ключ в коллекции типа SortedList, вызывается метод ContainsKey(). А если требуется выяснить, хранится ли конкретное значение в коллекции типа SortedList, вызывается метод ContainsValue(). Для перечисления содержимого коллекции типа SortedList служит метод GetEnumerator(), возвращающий объект типа IDictionaryEnumerator. Напомним, что IDictionaryEnumerator — это перечислитель, используемый для перечисления содержимого коллекции, в которой хранятся пары "ключ-значение". И наконец, для получения синхронизированной оболочки, в которую заключается коллекция типа SortedList, вызывается метод Synchronized().

Таблица 25.6. Наиболее часто используемые методы, определенные в классе SortedList

Метод - Описание

public virtual bool ContainsKey(object key) - Возвращает логическое значение true, если в вызывающей коллекции типа SortedList содержится ключ key, а иначе — логическое значение false

public virtual bool ContainsValue(object value) - Возвращает логическое значение true, если в вызывающей коллекции типа SortedList содержится значение value, а иначе — логическое значение false

public virtual object GetBylndex(int index) - Возвращает значение, указываемое по индексу index

public virtual IDictionaryEnumerator GetEnumerator() - Возвращает для вызывающей коллекции типа SortedList перечислитель типа IDictionaryEnumerator

public virtual object GetKey(int index) - Возвращает значение ключа, указываемое по индексу index

public virtual IList GetKeyList() - Возвращает коллекцию типа SortedList с ключами, хранящимися в вызывающей коллекции типа SortedList

public virtual IList GetValueList() - Возвращает коллекцию типа SortedList со значениями, хранящимися в вызывающей коллекции типа SortedList

public virtual int IndexOfKey(object key) - Возвращает индекс ключа key. Если искомый ключ не обнаружен, возвращается значение -1

public virtual int IndexOfValue(object value) - Возвращает индекс первого вхождения значения value в вызывающей коллекции. Если искомое значение не обнаружено, возвращается значение -1

public virtual void SetBylndex(int index,object  value) - Устанавливает значение по индексу index равным значению value

public static SortedList Synchronized(SortedList list) - Возвращает синхронизированный вариант коллекции типа SortedList, передаваемой в качестве параметра list

public virtual void TrimToSize() - Устанавливает значение свойства Capacity равным значению свойства Count

Ключ или значение можно получить разными способами. В частности, для получения значения по указанному индексу служит метод GetByIndex(), а для установки значения по указанному индексу — метод SetByIndex(). Для извлечения ключа по указанному индексу вызывается метод GetKey(), а для получения списка ключей по указанному индексу — метод GetKeyList(). Кроме того, для получения списка всех значений из коллекции служит метод GetValueList(). Для получения индекса ключа вызывается метод IndexOfKey(), а для получения индекса значения — метод IndexOfValue(). Безусловно, в классе SortedList также поддерживается индексатор, определяемый в интерфейсе IDictionary и позволяющий устанавливать и получать значение по заданному ключу.

В классе SortedList доступны также открытые свойства, определенные в тех интерфейсах, которые в нем реализуются. Как и в классе Hashtable, в данном классе особая роль принадлежит двум свойствам, Keys и Values, поскольку с их помощью можно получить доступную только для чтения коллекцию ключей или значений из коллекции типа SortedList. Эти свойства определяются в интерфейсе IDictionary следующим образом.

public virtual ICollection Keys { get; }
public virtual ICollection Values { get; }

Порядок следования ключей и значений отражает порядок их расположения в коллекции типа SortedList.

Аналогично коллекции типа Hashtable, пары "ключ-значение" сохраняются в коллекции типа SortedList в форме структуры типа DictionaryEntry, но, как правило, доступ к ключам и значениям осуществляется по отдельности с помощью методов и свойств, определенных в классе SortedList.

В приведенном ниже примере программы демонстрируется применение класса SortedList. Это переработанный и расширенный вариант предыдущего примера, демонстрировавшего применение класса Hashtable, вместо которого теперь используется класс SortedList. Глядя на результат выполнения этой программы, вы можете сами убедиться, что теперь список полученных значений оказывается отсортированным по заданному ключу.

// Продемонстрировать применение класса SortedList.
using System;
using System.Collections;
class SLDemo {
  static void Main() {
    // Создать отсортированный список.
    SortedList si = new SortedList();
    // Добавить элементы в список.
    si.Add("здание", "жилое помещение");
    si.Add("автомашина", "транспортное средство");
    si.Add("книга", "набор печатных слов");
    si.Add("яблоко", "съедобный плод");
    // Добавить элементы с помощью индексатора,
    si["трактор"] = "сельскохозяйственная машина";
    // Получить коллекцию ключей.
    ICollection с = si.Keys;
    // Использовать ключи для получения значений.
    Console.WriteLine("Содержимое списка по индексатору.");
    foreach(string str in с)
      Console.WriteLine(str + ": " + si[str]);
    Console.WriteLine();
    // Отобразить список, используя целочисленные индексы.
    Console.WriteLine("Содержимое списка по целочисленным индексам.");
    for(int i=0; i < si.Count; i++)
      Console.WriteLine(si.GetByIndex(i)) ;
    Console.WriteLine() ;
    // Показать целочисленные индексы элементов списка.
    Console.WriteLine("Целочисленные индексы элементов списка.");
    foreach(string str in с)
      Console.WriteLine(str + ": " + si.IndexOfKey(str));
  }
}

Ниже приведен результат выполнения этой программы.

Содержимое списка по индексатору.
автомашина: транспортное средство
здание: жилое помещение
книга: набор печатных слов
трактор: сельскохозяйственная машина
яблоко: съедобный плод
Содержимое списка по целочисленным индексам.
транспортное средство
жилое помещение
набор печатных слов
сельскохозяйственная машина
съедобный плод
Целочисленные индексы элементов списка.
автомашина: 0
здание: 1
книга: 2
трактор: 3
яблоко: 4

Класс Stack

Как должно быть известно большинству читателей, стек представляет собой список, действующий по принципу "первым пришел — последним обслужен". Этот принцип действия стека можно наглядно представить на примере горки тарелок, стоящих на столе. Первая тарелка, поставленная в эту горку, извлекается из нее последней. Стек относится к одним из самых важных структур данных в вычислительной технике. Он нередко применяется, среди прочего, в системном программном обеспечении, компиляторах, а также в программах отслеживания в обратном порядке на основе искусственного интеллекта

Класс коллекции, поддерживающий стек, носит название Stack. В нем реализуются интерфейсы ICollection, IEnumerable и ICloneable. Этот класс создает динамическую коллекцию, которая расширяется по мере потребности хранить в ней вводимые элементы. Всякий раз, когда требуется расширить такую коллекцию, ее емкость увеличивается вдвое.

В классе Stack определяются следующие конструкторы.

public Stack()
public Stack(int initialCapacity)
public Stack(ICollection col)

В первой форме конструктора создается пустой стек, во второй форме — пустой стек, первоначальный размер которого определяет первоначальная емкость, задаваемая параметром initialCapacity, ив третьей форме — стек, содержащий элементы указываемой коллекции col. Его первоначальная емкость равна количеству указанных элементов.

В классе Stack определяется ряд собственных методов, помимо тех, что уже объявлены в интерфейсах, которые в нем реализуются. Некоторые из наиболее часто используемых методов этого класса приведены в табл. 25.7. Эти методы обычно применяются следующим образом. Для того чтобы поместить объект на вершине стека, вызывается метод Push(). А для того чтобы извлечь и удалить объект из вершины стека, вызывается метод Pop(). Если же объект требуется только извлечь, но не удалить из вершины стека, то вызывается метод Реек(). А если вызвать метод Pop() или Реек(), когда вызывающий стек пуст, то сгенерируется исключение InvalidOperationException.

Таблица 25.7. Наиболее часто используемые методы, определенные в классе Stack

Метод - Описание

public virtual void Clear() - Устанавливает свойство Count равным нулю, очищая, по существу, стек

public virtual bool Contains (object obj) - Возвращает логическое значение true, если объект obj содержится в вызывающем стеке, а иначе — логическое значение false

public virtual object Peek() -  Возвращает элемент, находящийся на вершине стека, но не удаляет его

public virtual object Pop() - Возвращает элемент, находящийся на вершине стека, удаляя его по ходу дела

public virtual void Push (object obj) - Помещает объект obj в стек

public static Stack Synchronized(Stack stack) - Возвращает синхронизированный вариант коллекции типа Stack, передаваемой в качестве параметра stack

public virtual object[] ToArray() - Возвращает массив, содержащий копии элементов вызывающего стека

В приведенном ниже примере программы создается стек, в который помещается несколько целых значений, а затем они извлекаются обратно из стека.

// Продемонстрировать применение класса Stack.
using System;
using System.Collections;
class StackDemo {
  static void ShowPush(Stack st, int a) {
    st.Push(a);
    Console.WriteLine("Поместить в стек: Push(" + a + ")");
    Console.Write("Содержимое стека: ");
    foreach(int i in st)
      Console.Write(i + " ");
    Console.WriteLine();
  }
  static void ShowPop(Stack st) {
    Console.Write("Извлечь из стека: Pop -> ");
    int a = (int) st.Pop();
    Console.WriteLine(а);
    Console.Write("Содержимое стека: ");
    foreach(int i in st)
      Console.Write(i + " ");
    Console.WriteLine();
  }
  static void Main() {
    Stack st = new Stack();
    foreach(int i in st)
      Console.Write(i + " ");
    Console.WriteLine();
    ShowPush(st, 22);
    ShowPush(st, 65);
    ShowPush(st, 91);
    ShowPop(st);
    ShowPop(st);
    ShowPop(st) ;
    try {
      ShowPop(st) ;
    } catch (InvalidOperationException) {
      Console.WriteLine("Стек пуст.");
    }
  }
}

Ниже приведен результат выполнения этой программы. Обратите внимание на то, как обрабатывается исключение InvalidOperationException, генерируемое при попытке извлечь элемент из пустого стека.

Поместить в стек: Push(22)
Содержимое стека: 22
Поместить в стек: Push(65)
Содержимое стека: 65 22
Поместить в стек: Push(91)
Содержимое стека: 91 65 22
Извлечь из стека: Pop -> 91
Содержимое стека: 65 22
Извлечь из стека: Pop -> 65
Содержимое стека: 22
Извлечь из стека: Pop -> 22
Содержимое стека:
Извлечь из стека: Pop -> Стек пуст.

Класс Queue

Еще одной распространейной структурой данных является очередь, действующая по принципу: первым пришел — первым обслужен. Это означает, что первым из очереди извлекается элемент, помещенный в нее первым. Очереди часто встречаются в реальной жизни. Многим из нас нередко приходилось стоять в очередях к кассе в банке, магазине или столовой. В программировании очереди применяются для хранения таких элементов, как процессы, выполняющиеся в данный момент в системе, списки приостановленных транзакций в базе данных или пакеты данных, полученные по Интернету. Кроме того, очереди нередко применяются в области имитационного моделирования.

Класс коллекции, поддерживающий очередь, носит название Queue. В нем реализуются интерфейсы ICollection, IEnumerable и ICloneable. Этот класс создает динамическую коллекцию, которая расширяется, если в ней необходимо хранить вводимые элементы. Так, если в очереди требуется свободное место, ее размер увеличивается на коэффициент роста, который по умолчанию равен 2,0.

В классе Queue определяются приведенные ниже конструкторы.

public Queue()
public Queue (int capacity)
public Queue (int capacity, float growFactor)
public Queue (ICollection col)

В первой форме конструктора создается пустая очередь с выбираемыми по умолчанию емкостью и коэффициентом роста 2,0. Во второй форме создается пустая очередь, первоначальный размер которой определяет емкость, задаваемая параметром capacity, а коэффициент роста по умолчанию выбирается для нее равным 2,0. В третьей форме допускается указывать не только емкость (в качестве параметра capacity), но и коэффициент роста создаваемой очереди (в качестве параметра growFactor в пределах от 1,0 до 10,0). И в четвертой форме создается очередь, состоящая из элементов указываемой коллекции col. Ее первоначальная емкость равна количеству указанных элементов, а коэффициент роста по умолчанию выбирается для нее равным 2,0.

В классе Queue определяется ряд собственных методов, помимо тех, что уже объявлены в интерфейсах, которые в нем реализуются. Некоторые из наиболее часто используемых методов этого класса перечислены в табл. 25.8. Эти методы обычно применяются следующим образом. Для того чтобы поместить объект в очередь, вызывается метод Enqueue(). Если требуется извлечь и удалить первый объект из начала очереди, то вызывается метод Dequeue(). Если же требуется извлечь, но не удалять следующий объект из очереди, то вызывается метод Реек(). А если методы Dequeue() и Реек() вызываются, когда очередь пуста, то генерируется исключение InvalidOperationException.

Таблица 25.8. Наиболее часто используемые методы, определенные в классе Queue

Метод - Описание

public virtual void Clear() - Устанавливает свойство Count равным нулю, очищая, по существу, очередь

public virtual bool Contains(object obj) - Возвращает логическое значение true, если объект obj содержится в вызывающей очереди, а иначе — логическое значение false

public virtual object Dequeue() - Возвращает объект из начала вызывающей очереди. Возвращаемый объект удаляется из очереди

public virtual void Enqueue(object obj) - Добавляет объект obj в конец очереди 

public virtual object Peek() - Возвращает объект из начала вызывающей очереди, но не удаляет его

public static Queue Synchronized(Queue queue) - Возвращает синхронизированный вариант коллекции типа Queue, передаваемой в качестве параметра queue

public virtual object[] ToArray() - Возвращает массив, который содержит копии элементов из вызывающей очереди

public virtual void TrimToSize() -  Устанавливает значение свойства Capacity равным значению свойства Count

В приведенном ниже примере программы демонстрируется применение класса

Queue.

// Продемонстрировать применение класса Queue.
using System;
using System.Collections;
class QueueDemo {
  static void ShowEnq(Queue q, int a) {
    q.Enqueue(a) ;
    Console.WriteLine("Поместить в очередь: Enqueue(" + a + ")");
    Console.Write("Содержимое очереди: ");
    foreach(int i in q)
      Console.Write(i + " ");
    Console.WriteLine() ;
  }
  static void ShowDeq(Queue q) {
    Console.Write("Извлечь из очереди: Dequeue -> ");
    int a = (int) q.Dequeue();
    Console.WriteLine(a);
    Console.Write("Содержимое очереди: ");
    foreach(int i in q)
      Console.Write(i + " ") ;
    Console.WriteLine();
  }
  static void Main() {
    Queue q = new Queue();
    foreach(int i in q)
      Console.Write(i + " ");
    ShowEnq(q, 22);
    ShowEnq(q, 65);
    ShowEnq(q, 91);
    ShowDeq(q);
    ShowDeq(q);
    ShowDeq(q);
    try {
      ShowDeq (q);
    } catch (InvalidOperationException) {
      Console.WriteLine("Очередь пуста.");
    }
  }
}

Эта программа дает следующий результат.

Поместить в очередь: Enqueue(22)
Содержимое очереди: 22
Поместить в очередь: Enqueue(65)
Содержимое очереди: 22 65
Поместить в очередь: Enqueue(91)
Содержимое очереди: 22 65 91
Извлечь из очереди: Dequeue -> 22
Содержимое очереди: 65 91
Извлечь из очереди: Dequeue -> 65
Содержимое очереди: 91
Извлечь из очереди: Dequeue -> 91
Содержимое очереди:
Извлечь из очереди: Dequeue -> Очередь пуста.

Оглавление книги


Генерация: 1.230. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз