Выбрать главу
(ArrayList list) Возвращает синхронизированный вариант коллекции типа ArrayList, передаваемой в качестве параметра list public virtual object[] ToArray() Возвращает массив, содержащий копии элементов вы зывающего объекта public virtual Array ToArray(Type type) Возвращает массив, содержащий копии элементов вы зывающего объекта. Тип элементов этого массива опре деляется параметром type public virtual void TrimToSize() Устанавливает значение свойства Capacity равным значению свойства Count перезаписи элементов коллекции типа 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('A'); 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 с in al) Console.Write(с + " "); 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 с in al) Console.Write(с + " "); Console.WriteLine("\n"); // Изменить содержимое динамического массива, // используя индексирование массива. Console.WriteLine("Изменить три первых элемента"); al[0] = 'X'; al[1] = 'Y'; al[2] = 'Z'; Console.Write("Содержимое: "); foreach(char с in al) Console.Write(c + " Console.WriteLine(); } } Вот к какому результату приводит выполнение этой программы. Исходное количество элементов: 0 Добавить 6 элементов Количество элементов: 6 Текущее содержимое: С А Е В D F Удалить 2 элемента Количество элементов: 4 Содержимое: С Е В D Добавить еще 20 элементов Текущая емкость: 32 Количество элементов после добавления 20 новых: 24 Содержимое: C E B 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 иногда требуется получить из ее содер жимого обычный массив. Этой цели служит метод ТоАrrау(). Для преобразования коллекции в массив имеется несколько причин. Две из них таковы: потребность в уско рении обработки при выполнении некоторых операций и необходимость передавать массив методу, который не перегружается, чтобы принять коллекцию. Но независимо от конкретной причины коллекция типа 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 "); int a = (int) st.Pop(); Метод Описание 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() Возвращает массив, содержащий копии элементов вызывающего стека Console.WriteLine(a); 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. Во второй форме создается пустая оче редь, первоначальный размер которой определяет емкость, задаваемая параметром сараcity, а коэффициент роста по умолчанию выбирается для нее равным 2,0. В тре тьей форме допускается указывать не только емкость (в качестве параметра capacity), но и коэффициент роста создаваемой очереди (в качестве параметра growFactor в пределах от 1,0 до 10,0). И в четвертой форме создается очередь, состоящая из элемен тов указываемой коллекции col. Ее первоначальная емкость равна количеству указан ных элементов, а коэффициент роста по умолчанию выбирается для нее равным 2,0. В классе Queue определяется ряд собственных методов, помимо тех, что уже объявлены в интерфейсах, которые в нем реализуются. Некоторые из наиболее ча сто используемых методов этого класса перечислены в табл. 25.8. Эти методы обыч но применяются следующим образом. Для того чтобы поместить объект в очередь, вызывается метод Enqueue(). Если требуется извлечь и удалить первый объект из начала очереди, то вызывается метод Dequeue(). Если же требуется извлечь, но не удалять следующий объект из очереди, то вызывается метод Рееk(). А если методы Dequeue() и Рееk() вызываются, когда очередь пуста, то генерируется исключение 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 в конец очереди Окончание табл. 25.8 Метод Описание 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 + " "); Console.WriteLine(); 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 -> Очередь пуста. Хранение отдельных битов в классе коллекции BitArray Класс BitArray служит для хранения отдельных битов в коллекции. А поскольку в коллекции этого класса хранятся биты, а не объекты, то своими возможностями он отличается от классов других коллекций. Тем не менее в классе BitArray реализуют ся интерфейсы ICollection и IEnumerable как основополагающие элементы под держки всех типов коллекций. Кроме того, в классе BitArray реализуется интерфейс ICloneable. В классе BitArray определено несколько конструкторов. Так, с помощью приве денного ниже конструктора можно сконструировать объект типа BitArray из массива логических значений. public BitArray(bool[] values) В данном случае каждый элемент массива values становится отдельным битом в коллекции. Это означает, что каждому элементу массива values соответствует отдель ный бит в коллекции. Более того, порядок расположения элементов в массиве values сохраняется и в коллекции соответствующих им битов. Коллекцию типа BitArray можно также составить из массива байтов, используя следующий конструктор. public BitArray(byte[] bytes) Здесь битами в коллекции становится уже целый их набор из массива bytes, при чем элемент bytes[0] обозначает первые 8 битов, элемент bytes[1] — вторые 8 би тов и т.д. Аналогично, коллекцию типа BitArray можно составить из массива цело численных значений, используя приведенный ниже конструктор. public BitArray(int[ ] values) В данном случае элемент values[0] обозначает первые 32 бита, элемент values[1] — вторые 32 бита и т.д. С помощью следующего конструктора можно составить коллекцию типа BitArray, указав ее конкретный размер: public BitArray(int length) где length обозначает количество битов в коллекции, которые инициализируются логическим значением false. В приведенном ниже конструкторе можно указать не только размер коллекции, но и первоначальное значение составляющих ее битов. public BitArray(int length, bool defaultValue) В данном случае все биты в коллекции инициализируются значением defaultValue, передаваемым конструктору в качестве параметра. И наконец, новую коллекцию типа BitArray можно создать из уже существую щей, используя следующий конструктор. public BitArray(BitArray bits) Вновь сконструированный объект будет содержать такое же количество битов, как и в указываемой коллекции bits, а в остальном это будут две совершенно разные кол лекции. Коллекции типа BitArray подлежат индексированию. По каждому индексу указы вается отдельный бит в коллекции, причем нулевой индекс обозначает младший бит. В классе BitArray определяется ряд собственных методов, помимо тех, что уже объявлены в интерфейсах, которые в нем реализуются. Методы этого класса приведе ны в табл. 25.9. Обратите внимание на то, что в классе BitArray не поддерживается метод Synchronized(). Это означает, что для коллекций данного класса синхронизи рованная оболочка недоступна, а свойство IsSynchronized всегда имеет логическое значение false. Тем не менее для управления доступом к коллекции типа BitArray ее можно синхронизировать для объекта, предоставляемого упоминавшимся ранее свойством SyncRoot. Таблица 25.9. Методы, определенные в классе BitArray Метод Описание public BitArray And(BitArray value) Выполняет операцию логического умножения И би тов вызывающего объекта и коллекции value. Воз вращает коллекцию типа BitArray, содержащую результат public bool Get(int index) Возвращает значение бита, указываемого по ин дексу index public BitArray Not() Выполняет операцию поразрядного логического отри цания НЕ битов вызывающей коллекции и возвраща ет коллекцию типа BitArray, содержащую результат Окончание табл. 25.9 В классе BitArray определяется также собственное свойство, помимо тех, что ука заны в интерфейсах, которые в нем реализуются. public int Length { get; set; } Свойство Length позволяет установить или получить количество битов в коллек ции. Следовательно, оно возвращает такое же значение, как и стандартное свойство Count, определяемое для всех коллекций. В отличие от свойства Count, свойство Length доступно не только для чтения, но и для записи, а значит, с его помощью мож но изменить размер коллекции типа BitArray. Так, при сокращении коллекции типа BitArray лишние биты усекаются, начиная со старшего разряда. А при расширении коллекции типа BitArray дополнительные биты, имеющие логическое значение false, вводятся в коллекцию, начиная с того же старшего разряда. Кроме того, в классе BitArray определяется следующий индексатор. public bool this[int index] { get; set; } С помощью этого индексатора можно получать или устанавливать значение элемента. В приведенном ниже примере демонстрируется применение класса BitArray. // Продемонстрировать применение класса BitArray. using System; using System.Collections; class BADemo { public static void ShowBits(string rem, BitArray bits) { Console.WriteLine(rem); for(int i=0; i < bits.Count; i++) Console.Write("{0, -6} ", bits[i]); Console.WriteLine("\n"); } static void Main() { BitArray ba = new BitArray(8); byte[] b = { 67 }; BitArray ba2 = new BitArray(b); Метод Описание public BitArray Or(BitArray value) Выполняет операцию логического сложения ИЛИ би тов вызывающего объекта и коллекции value. Воз вращает коллекцию типа BitArray, содержащую результат public void Set(int index, bool value) Устанавливает бит, указываемый по индексу Index, равным значению value public void SetAll(bool value) Устанавливает все биты равными значению value public BitArray Xor(BitArray value) Выполняет логическую операцию исключающее ИЛИ над битами вызывающего объекта и коллекции value. Возвращает коллекцию типа BitArray, со держащую результат ShowBits("Исходное содержимое коллекции ba:", bа); ba = ba.Not(); ShowBits("Содержимое коллекции bа после логической операции NOT:", ba); ShowBits("Содержимое коллекции bа2:", bа2); BitArray bа3 = bа.Хоr(bа2); ShowBits("Результат логической операции ba XOR bа2:", bаЗ); } } Эта программа дает следующий результат. Исходное содержимое коллекции Ьа: False False False False False False False False Содержимое коллекции ba после логической операции NOT: True True True True True True True True Содержимое коллекции bа2: True True False False False False ffrue False Результат логической операции ba XOR ba2: False False True True True True False True Специальные коллекции В среде .NET Framework предусмотрен ряд специальных коллекций, оптимизиро ванных для работы с данными конкретного типа иди для их обработки особым обра зом. Классы этих необобщенных коллекций определены в пространстве имен System. Collections.Specialized и перечислены ниже. Класс специальной коллекции Описание CollectionsUtil Содержит фабричные методы для создания коллекций HybridDictionary Предназначен для коллекций, в которых для хранения неболь шого количества пар “ключ-значение" используется класс ListDictionary. При превышении коллекцией определен ного размера автоматически используется класс Hashtable для хранения ее элементов ListDictionary Предназначен для коллекций, в которых для хранения пар “ключ- значение” используется связный список. Такие коллекции реко мендуются только для хранения небольшого количества элементов NameValueCollection Предназначен для отсортированных коллекций, в которых хра нятс