Выбрать главу

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

Массивами в Java можно пользоваться практически так же, как и в других языках программирования. Тем не менее у них имеется одна особенность: они реализованы в виде объектов. Именно поэтому их рассмотрение было отложено до тех пор, пока в этой книге не были представлены объекты. Реализация массивов в виде объектов дает ряд существенных преимуществ, и далеко не самым последним среди них является возможность утилизировать неиспользуемые массивы средствами “сборки мусора”. Одномерные массивы

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

Для объявления одномерного массива обычно применяется следующая общая форма: тип имя_массива[] = new тип[размер];

где тип объявляет конкретный тип элемента массива. Тип элемента, называемый также базовым, определяет тип данных каждого элемента, составляющего массив. А размер определяет число элементов массива. В связи с тем что массивы реализованы в виде объектов, создание массива происходит в два этапа. Сначала объявляется переменная, ссылающаяся на массив, затем выделяется память для массива, а ссылка на нее присваивается переменной массива. Следовательно, память для массивов в Java динамически распределяется с помощью оператора new.

Проиллюстрируем все сказанное выше на конкретном примере. В следующей строке кода создается массив типа int, состоящий из 10 элементов, а ссылка на него присваивается переменной sample: int sample[] = new int[10];

Объявление массива происходит так же, как и объявление объекта. В переменной sample сохраняется ссылка на область памяти, выделяемую для массива оператором new. Этой памяти должно быть достаточно для размещения в ней 10 элементов типа int.

Как и объявление объектов, приведенное выше объявление массива можно разделить на две отдельные составляющие следующим образом: int sample []; sample = new int[10];

В данном случае сначала создается переменная sample, которая пока что не ссылается на конкретный объект. А затем переменная sample получает ссылку на конкретный массив.

Доступ к отдельным элементам массива осуществляется с помощью индексов. Индекс обозначает положение элемента в массиве. В Java индекс первого элемента массива равен нулю. Так, если массив sample содержит 10 элементов, их индексы находятся в пределах от 0 до 9. Индексирование массива осуществляется по номерам его элементов, заключенным в квадратные скобки. Например, для доступа к первому элементу массива sample следует указать sample [ 0 ], а для доступ к последнему элементу этого массива — sample [9]. В приведенном ниже примере программы в массиве sample сохраняются числа от 0 до 9. // Демонстрация одномерного массива, class ArrayDemo { public static void main(String args[]) { int sample[] = new int[10]; int i; // Массивы индексируются с нуля, как показано ниже. for(i = 0; i < 10; i = i+1) sample[i] = i; for(i =0; i < 10; i = i+1) System.out.println("This is sample[" + i + "] : " + sample [i]); } }

Результат выполнения данной программы выглядит следующим образом: This is sample[0]: 0 This is sample[1]: 1 This is sample[2]: 2 This is sample[3]: 3 This is sample[4]: 4 This is sample[5]: 5 This is sample[6]: 6 This is sample[7]: 7 This is sample[8]: 8 This is sample[9]: 9

Структура массива sample наглядно показана на приведенном ниже рисунке. Массивы часто употребляются в программировании, поскольку они позволяют обрабатывать в цикле большое количество переменных. Например, в результате выполнения следующего примера программы определяется минимальное и максимальное значения из всех, хранящихся в массиве nums. Элементы этого массива перебираются в цикле for. // Нахождение минимального и максимального значений в массиве, class MinMax { public static void main(String args[]) { int nums[] = new int[10]; int min, max; nums[0] = 99; nums[l] = -10; nums[2] = 100123; nums[3] = 18; nums[4] = -978; nums[5] = 5623; nums[6] = 4 63; nums[7] = -9; nums[8] =287; nums[9] = 4 9; min = max = nums[0]; for(int i=l; i < 10; i++) { if(nums[i] < min) min = nums[i]; if(nums[i] > max) max = nums[i]; } System.out.println("min and max: " + min + " " + max); } }

Ниже приведен результат выполнения данной программы. min and max: -978 100123

В приведенном выше примере программы массив nums заполняется вручную в десяти операторах присваивания. И хотя в этом нет ничего неверного, существует более простой способ решения той же самой задачи. Массивы можно инициализировать в процессе их создания. Для этой цели служит приведенная ниже общая форма инициализации массива. тип имя_массива[] = {vail, val2, val3, ..., valN} ;

где vall-valN обозначают первоначальные значения, которые присваиваются элементам массива по очереди, слева направо и по порядку индексирования. Для хранения инициализаторов массива в Java автоматически распределяется достаточный объем памяти. А необходимость пользоваться оператором new явным образом отпадает сама собой. В качестве примера ниже приведена улучшенная версия программы, в которой определяются максимальное и минимальное значения в массиве. // Применение инициализаторов массива, class MinMax2 { public static void main(String args[]) { // Инициализаторы массива. int nums[] = { 99, -10, 100123, 18, -978, 5623, 463, -9, 287, 49 }; int min, max; min = max = nums[0]; for(int i=l; i < 10; i++) { if(nums[i] < min) min = nums[i]; if(nums[i] > max) max = nums[i]; } System.out.println("Min and max: " + min + " " + max); } }

Границы массива в Java строго соблюдаются. Если границы массива не достигаются или же превышаются, при выполнении программы возникает ошибка. Для того чтобы убедиться в этом, попробуйте выполнить приведенную ниже программу, в которой намеренно превышаются границы массива. // Демонстрация превышения границ массива, class ArrayErr { public static void main(String args[]) { int sample[] = new int[10]; int i; // воссоздать превышение границ массива for(i = 0; i < 100; i = i+1) sample[i] = i; } }

Как только значение переменной i достигнет 10, будет сгенерировано исключение ArraylndexOutOfBoundsException и выполнение программы прекратится.

Пример для опробования 5.1. Сортировка массива

Как пояснялось выше, данные в одномерном массиве организованы в виде индексируемого линейного списка. Такая структура как нельзя лучше подходит для сортировки. В этом проекте предстоит реализовать простой алгоритм сортировки массива. Вам, вероятно, известно, что существуют разные алгоритмы сортировки, в том числе быстрая сортировка, сортировка перемешиванием, сортировка методом Шелла. Но самым простым и общеизвестным алгоритмом является пузырьковая сортировка. Этот алгоритм не очень эффективен, но отлично подходит для сортировки небольших массивов.

Последовательность действий

Создайте новый файл Bubble. j ava.

В алгоритме пузырьковой сортировки соседние элементы массива сравниваются и меняются, если требуется, местами. При этом малые значения сдвигаются к одному краю массива, а большие значения — к другому. Этот процесс напоминает всплывание пузырьков воздуха на разные уровни в емкости с жидкостью, откуда и произошло название данного алгоритма. Пузырьковая сортировка предполагает обработку массива в несколько проходов. Элементы, взаимное расположение которых отличается от требуемого, меняются местами. Число проходов должно быть таким, чтобы все элементы непременно встали на свои места. Максимальное количество проходов должно быть на один меньше, чем число элементов в массиве. Ниже приведен исходный код, составляющий основу алгоритма пузырьковой сортировки. Сортируемый массив называется nums. // Это пример реализации алгоритма пузырьковой сортировки. for(a=l; а < size; а++) for(b=size-l; b >= a; b—) { if(nums[b-l] > nums[b]) { // если требуемый порядок следования // не соблюдается, поменять элементы местами t = nums[b—1]; nums[b-l] = nums[b]; nums[b] = t; } } Как видите, в приведенном выше фрагменте кода используются два цикла for. Во внутреннем цикле сравниваются соседние элементы массива и выявляются элементы, находящиеся не на своих местах. Если обнаружен элемент, положение которого отличается от требуемого, то два соседних элемента меняются местами. На каждом проходе наименьший элемент передвигается на один шаг в нужное положение. Внешний цикл обеспечивает повторение описанного выше процесса до тех пор, пока сортировка массива не будет завершена.