Урок 35. Коллекция ArrayList C#: часть вторая


Продолжаем изучать ArrayList. В этом материале пойдёт речь о сортировке, двоичном поиске, получении диапазона значений, методы копирования, работа с емкостью и синхронизация ArrayList. Начало - Урок 35. Коллекция ArrayList C#: часть первая. Все уроки по C#.

Сортировка ArrayList

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

Когда ArrayList содержит объекты, каждый объект должен реализовать интерфейс IComparable и обеспечить совместимые сравнения. Этот интерфейс предоставляет информацию, необходимую для определения порядка. Упорядочение объектов с помощью IComparable выходит за рамки базового учебника. Важно отметить, что типы объектов должны быть сопоставимы. Например, невозможно отсортировать список ArrayList, содержащий как буквенно-цифровые строки, так и целочисленные значения.

В следующем примере используется метод Sort для упорядочивания списка ArrayList, содержащего строки:

ArrayList myCollection = new ArrayList(
    new string[] {"One", "Two", "Three", "Four", "Five"});
 
myCollection.Sort();
 
foreach (string s in myCollection)
{
    Console.WriteLine(s);
}
 
/* Вывод
 
Five
Four
One
Three
Two
 
*/
Примечание: существуют и другие перегруженные версии сортировки. Они позволяют задать различные параметры сортировки и разрешить сортировку диапазона значений в списке ArrayList.

Бинарный поиск

Двоичный поиск является более эффективным методом, с помощью которого можно найти элемент в отсортированном списке. Вместо циклического перебора всех значений в коллекции проверяется среднее значение. Если это значение больше, чем значение для поиска, проверяется другой элемент на полпути между низким значением и начальным поиском. Если значение меньше, происходит обратное. Каждый раз, когда элемент сравнивается в ArrayList, половина оставшихся элементов может быть немедленно дисконтирована как потенциальные соответствия. Чтобы продемонстрировать разницу в эффективности, для поиска 65 536 элементов ArrayList с использованием IndexOf может потребоваться 65 536 индивидуальных сравнений. При использовании бинарного алгоритма поиска, максимальное количество тестов - шестнадцать.

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

ArrayList myCollection = new ArrayList(
    new string[] {"One", "Two", "Three", "Four", "Five"});
 
myCollection.Sort();
 
foreach (string s in myCollection)
{
    Console.WriteLine(s);
}
 
Console.WriteLine("'One' found at index {0}", myCollection.BinarySearch("One"));
 
/* Вывод
 
Five
Four
One
Three
Two
'One' found at index 2
 
*/
Получение диапазона значений

Метод GetRange можно использовать для извлечения диапазона значений из списка ArrayList. Этот метод позволяет задать начальный индекс и количество элементов. Соответствующие элементы возвращаются в новом списке ArrayList.

ArrayList myCollection = new ArrayList(
    new string[] {"One", "Two", "Three", "Four", "Five"});
 
ArrayList extract = myCollection.GetRange(1,3);
 
foreach (string s in extract)
{
    Console.WriteLine(s);
}
 
/* Вывод
 
Two
Three
Four
 
*/
Копирование ArrayList

Копирование в массив

Поскольку класс ArrayList реализует интерфейс IList, он поддерживает использование метода CopyTo для копирования содержимого коллекции в одномерный массив. Кроме того, ArrayList предоставляет две перегруженные версии метода. Первый не требует никаких параметров и просто копирует все содержимое коллекции в существующий массив. Массив должен быть совместим с типами объектов в ArrayList, чтобы избежать исключения .

ArrayList myCollection = new ArrayList(
    new string[] {"One", "Two", "Three", "Four", "Five"});
 
string[] array = new string[5];
 
myCollection.CopyTo(array);
 
foreach (string s in array)
{
    Console.WriteLine(s);
}
 
/* Вывод
 
One
Two
Three
Four
Five
 
*/
Второй перегруженный метод CopyTo требует четырех параметров. Первый указывает индекс нуля в ArrayList, из которого выполняется копирование. Второй - это сам объект ArrayList. Третий содержит первый индекс в целевом массиве для получения скопированных элементов, и последний параметр определяет, сколько записей из коллекции должно быть скопировано. Это позволяет скопировать подмножество данных из списка ArrayList в существующий массив.

ArrayList myCollection = new ArrayList(
    new string[] {"One", "Two", "Three", "Four", "Five"});
 
string[] array = new string[5];
 
myCollection.CopyTo(1,array,0,3);
 
foreach (string s in array)
{
    Console.WriteLine(s);
}
 
/* Вывод
 
Two
Three
Four
 
*/
Существует еще одна функция, которая позволяет извлекать содержимое ArrayList в массив. Метод ToArray возвращает новый массив объектов. Это означает, что массив не нужно создавать до копирования. Однако базовый метод создает только массив экземпляров объекта. В следующем примере элементы ArrayList копируются в ряд объектов; каждый из них представляет собой прямоугольную строку.

ArrayList myCollection = new ArrayList(
    new string[] {"One", "Two", "Three", "Four", "Five"});
 
object[] array = myCollection.ToArray();
 
foreach (object o in array)
{
    Console.WriteLine(s);
}
 
/* Вывод
 
One
Two
Three
Four
Five
 
*/
Если ArrayList содержит коллекцию элементов, которые все имеют один и тот же тип, то этот тип может быть указан при использовании ToArray. Если каждый элемент коллекции может быть успешно приведен к указанному типу, то при копировании создается новый массив этого типа. Для указания типа компилятору используется команда typeof. Эта команда принимает в качестве параметра имя соответствующего класса или типа данных. Важно отметить, что метод по-прежнему возвращает массив объектов. Однако, поскольку типы элементов массива являются согласованными, весь массив может быть приведен к правильному типу.

В следующем примере обратите внимание на использование typeof (string) для указания типа каждого элемента массива для копирования. Также обратите внимание на приведение массива объектов к строковому массиву с помощью оператора cast (string[]) .

ArrayList myCollection = new ArrayList(
    new string[] {"One", "Two", "Three", "Four", "Five"});
 
string[] array = (string[])myCollection.ToArray(typeof(string));
 
foreach (string s in array)
{
    Console.WriteLine(s);
}
 
/* Вывод
 
One
Two
Three
Four
Five
 
*/
Емкость ArrayList

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

Емкость ArrayList может быть получена и изменена с помощью свойства Capacity. Это целое число.

ArrayList myCollection = new ArrayList();
 
int capacity = myCollection.Capacity;
Console.WriteLine("Default capacity is {0} items", capacity);
 
myCollection.Capacity = 40;
capacity = myCollection.Capacity;
Console.WriteLine("New capacity is {0} items", capacity);
 
/* Вывод
 
Default capacity is 16 items
New capacity is 40 items
 
*/
Как только ArrayList будет полностью заполнен и никакие другие элементы не будут добавлены, память, выделенная для неиспользуемой части коллекции, может быть восстановлена. Метод Trimmtosize задает емкость коллекции для соответствия текущему содержимому.

ArrayList myCollection = new ArrayList();
 
myCollection.Add("One");
myCollection.Add("Two");
myCollection.Add("Three");
myCollection.Add("Four");
myCollection.Add("Five");
 
int capacity = myCollection.Capacity;
Console.WriteLine("Initial capacity is {0} items", capacity);
 
myCollection.TrimToSize();
capacity = myCollection.Capacity;
Console.WriteLine("New capacity is {0} items", capacity);
 
/* Вывод
 
Initial capacity is 16 items
New capacity is 5 items
 
*/
Создание ArrayList фиксированного размера

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

Примечание: новые элементы могут быть добавлены в базовый список ArrayList. Они будут добавлены в коллекцию фиксированного размера без каких-либо исключений.

ArrayList myCollection = new ArrayList(
    new string[] {"One", "Two", "Three", "Four", "Five"});
 
ArrayList myFixed = ArrayList.FixedSize(myCollection);
 
Console.WriteLine(myFixed.IsFixedSize);     // Выводs "True"
 
myFixed.Add("Six");                         // Throws a NotSupportedException
Создание ArrayList только для чтения

В некоторых случаях оболочка фиксированного размера для ArrayList недостаточно ограничительна. Иногда бывает полезно создать коллекцию обертки, которая доступна только для чтения. Этот тип ArrayList, генерируемый статическим методом ReadOnly, вызывает исключение NotSupportedException, если сделана какая-либо попытка изменить его содержимое. Базовый ArrayList может быть изменен.

ArrayList myCollection = new ArrayList(
    new string[] {"One", "Two", "Three", "Four", "Five"});
 
ArrayList myReadOnly = ArrayList.ReadOnly(myCollection);
 
Console.WriteLine(myReadOnly.IsFixedSize);  // Выводs "True"
Console.WriteLine(myReadOnly.IsReadOnly);   // Выводs "True"
 
myReadOnly[0] = "Apple";                    // Throws a NotSupportedException
Создание синхронизированного ArrayList

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

ArrayList myCollection = new ArrayList(
    new string[] {"One", "Two", "Three", "Four", "Five"});
 
ArrayList myThreadSafe = ArrayList.Synchronized(myCollection);
 
Console.WriteLine(myThreadSafe.IsSynchronized);     // Выведет "True"
Предоставление функциональности ArrayList другим классам IList

Функциональные возможности, предоставляемые классом коллекции ArrayList, очень гибки при чтении, запросе и настройке содержимого коллекции. Функциональные возможности , например предоставляемые методами BinarySearch, Sort и Reverse, полезны во многих ситуациях. Однако иногда не следует использовать ArrayList в каждой ситуации, даже если эта функциональность может потребоваться.

Класс ArrayList включает статический метод с именем Adapter . Это создает оболочку ArrayList для других классов, реализующих IList, включая базовые массивы. Обернув подходящий массив или коллекцию, можно применить функциональность ArrayList, которая обычно недоступна для базового класса.

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

string[] numbers = new string[] {"One", "Two", "Three", "Four", "Five"};
 
ArrayList wrapper = ArrayList.Adapter(numbers);
 
wrapper.Sort();
 
foreach (string s in wrapper)
{
    Console.WriteLine(s);
}
 
Console.WriteLine("'One' Найден в индексе {0}", wrapper.BinarySearch("One"));
 
/* Вывод
 
Five
Four
One
Three
Two
'One' найден в индексе 2
 
*/
Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.

тегистатьи IT, си шарп, коллекции, уроки по си шарп, ArrayList




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




Урок 22. hashcode и equals в Java: часть 2
Ошибка 0xc000007b при запуске Visual Studio 2013
Почему MySQLi лучше MySQL?