Содержание
В программировании часто работают с такой математической структурой как массив. В языке Java он рассматривается как некая группа элементов одного типа.
Массив — это структура фиксированного размера, ее нельзя динамически изменять, как, например, это реализовано в коллекциях Java. У массивов есть масса применений — от анализа статистических данных и анализа их структуры до матричных вычислений и векторных операций.
Поскольку массив в Java является объектом, для его создания используется привычный способ: задается переменная (под именем которой мы будем подразумевать сам массив, хотя на самом деле она хранит лишь ссылку на него), а затем с помощью оператора new
описываем структуру массива.
Важная характеристика массива — его размерность.
Размерность — это количество индексов, необходимых для обращения к элементу массива. Доступ к любому компоненту массива осуществляется при помощи идентификатора, который называется индексом элемента.
При этом следует иметь в виду: нумерация элементов массива начинается с нуля. Чаще всего задействуются одномерные массивы, массивы же кратностью более двух используются на практике крайне редко.
Важно: в Java-массиве нельзя смешивать типы полей.
Java-массив
Команда для задания массива выглядит так:
типэлементов[] имя_переменной;
или так:
типэлементов имя_переменной[];
Обе записи — равнозначны.
Процесс генерирования массива и запись ссылки на него в переменную выглядит так:
типэлементов[] переменная;
переменная=new типэлементов [размер_массива];
Для обеих команд допускается более краткая форма:
типэлементов[] переменная=new типэлементов[размер_массива];
Рассмотрим общие формы для объявления одномерного массива.
Объявление массива | Пример | Комментарий |
type variable_name [] | int anArray [] | Java-стиль |
type [] variable_name | int [] anArray | Стиль, перекочевавший в Java из языка программирования С |
При использовании такого объявления мы должны знать, что фактического массива пока не существует. Тут мы просто отправляем сообщение компилятору, о том, что поле anArray
когда-нибудь будет приспособлено под массив с целыми числами. Чтобы связать anArray
с реальным целочисленным массивом, нужно объявить его с помощью ключевого слова new
:
int[] anArray = new int[10];
В примере числовое значение в квадратных скобках показывает количество слотов под элементы массива. В нашем случае мы выделяем под массив десять ячеек памяти.
Например:
int [] anArray; // объявление массива anArray = new int [20]; // выделяем память для массива
Или:
int [] intArray = new int [20]; // объединяем объявление с выделением памяти
Примечание: ячейкам в массиве, выделенным при помощи ключевого слова new
, будут автоматически присвоены значения: 0 (для числового типа), false (для логического) и null (для ссылок).
Предположим, мы хотим создать массив целых чисел на 13 элементов. Присвоим группе элементов имя — highloadToday:
int[] highloadToday = new int[13];
Выведем на экран длину массива:
System.out.println(highloadToday.length);
В консоли отобразится 13.
Аналогично создаются наборы данных других типов. Например, эта команда объявляет массив с десятью переменными типа double
и присваивает ссылку firstList
:
double[] firstList = new double[10];
Мы с вами разобрались, что длиной массива является число ячеек, выделенное для хранения данных, и эту длину невозможно будет изменить, когда массив уже создан. В Java счет элементов по порядку в массиве начинается не с единицы, а с нуля.
Как узнать длину массива
Чтобы узнать длину нашего массива, используем его свойство length
. Например:
int[] anArray = new int[10]; // создаем целочисленный массив на 10 ячеек и присваиваем ему имя anArray System.out.println(anArray.length); // выводим длину нашего массива
Теперь мы знаем, что такое массив, но как его использовать — пока непонятно. Как загружать в него информацию, а потом ее оттуда извлекать? Давайте разбираться.
В широком смысле массив — это самая важная структура данных в программировании. Сам компьютер — это не что иное, как набор массивов. Байт — это массив из восьми двоичных разрядов, а строка — это массив символов.
Разработчики используют массивы, потому что они работают быстро и позволяют напрямую обращаться к данным отдельного элемента за один компьютерный цикл независимо от размера массива.
Из-за операционной системы, виртуальной памяти и других факторов для извлечения элемента из массива может потребоваться несколько больше, чем один фактический компьютерный цикл. Но время извлечения первого элемента такое же, как и 100-го элемента и 500-тысячного. Никакая другая созданная нами структура данных не может быть быстрее, чем массив. Все «продвинутые» системы реализованы с их использованием.
Теперь давайте выясним особенности работы с этой полезной штукой. При объявлении создается массив в каждой ячейке которого — данные по умолчанию (это мы разобрали). Чтобы записать туда необходимые нам данные, нужно провести обряд инициализации, то есть присвоить каждой ячейке определенное значение.
Например, создадим массив, содержащий в себе четыре стороны света, и заполним его значениями:
String[] sides = new String[4]; /* объявленному массиву Java выделил память для четырех строк (по умолчанию их значение будет null, потому что String относится к ссылочному типу)*/sides[0] = "North"; /* Получив доступ к первой ячейке (с нулевым индексом), мы вписали туда строковое значение */sides[1] = "South"; // тоже самое мы проделываем с ячейкой под индексом 1 sides[2] = "West"; // 2 sides[3] = "East"; // 3
Мы используем индексы для доступа к ячейкам массива, число в скобках обозначает каждую конкретную позицию. Если переданный при доступе к ячейке индекс — отрицательный или превышает длину массива, Java выдаст исключение ArrayIndexOutOfBoundException
.
Теперь совместим инициализацию с объявлением:
String[] sides = new String[] {"North", "South", "West", "East"};
И уберем оператор new
, тем самым упростив запись:
String[] sides = {"North", "South", "West", "East"};
Есть несколько способов перебора массивов, один из них — циклический, например, с помощью цикла for
:
String[] sides = new String[] {"North", "South", "West", "East"}; for (int i = 0; i < 4; i++) { System.out.println(sides[i]); }
Выведет:
North South West East
Массивы, у которых только один индекс называется одномерным, мы уже рассмотрели. Но в них можно помещать не только примитивные типы данных и ссылки на объекты, но и другие массивы. В таком случае их называют многомерными.
Давайте на примере выясним, что они из себя представляют. Предположим, нам нужен массив для хранения числа имеющихся свободных мест в кинотеатре. Вот визуальное представление того, о чем я говорю:
Конечно в реальной жизни кинотеатр был бы больше, но этот нам как раз подойдет в качестве примера.
0 — означает, что место доступно, 1 — что занято. Мы также могли бы добавить еще и 2 для зарезервированных мест и так далее. Но пока ограничимся более простым примером.
Java не предоставляет никакой специальной поддержки для многомерных массивов, но мы можем легко объявить их как массив массивов. Это будет выглядеть вот так:
int [] [] cinema = новый int [5] [5];
Первое число указывает количество столбцов, второе — количество строк. Все числовые массивы в Java автоматически инициализируются нулевыми значениями после объявления. Мы только что создали таблицу, полную нулей.
Теперь давайте заполним кинозал единицами, как на картинке выше. Для создания строки из единиц используем несколько циклов for
. Чтобы открыть доступ к элементам 2D-массива, мы должны ввести координаты столбцов и строк:
cinema[2][2] = 1; // центр for (int i = 1; i < 4; i++) { // четвертая строка cinema[i][3] = 1; } for (int i = 0; i < 5; i++) { // последняя строка cinema[i][4] = 1; }
Нужно иметь в виду, что если мы запросим cinema.length
, он будет содержать количество столбцов (длину внешнего массива, представляющего столбцы). Чтобы определить количество строк (длину внутреннего массива), необходимо запросить cinema [0].length
. Обратите внимание, что для работы должен быть хотя бы один столбец.
Мы будем вкладывать циклы по порядку, чтобы внешний цикл проходил по строкам, а внутренний — по столбцам текущей строки. После вывода строки в консоль мы должны разорвать ее, ведь оба цикла должны иметь разные управляющие переменные:
for (int j = 0; j < cinema[0].length; j++) { for (int i = 0; i < cinema.length; i++) { System.out.print(cinema[i][j]); } System.out.println(); }
Результат:
00000 00000 00100 01110 11111
Иногда может быть полезно создать массив с большим количеством измерений. Например, трехмерный. Вернемся к примеру с кинотеатром. Теперь представим, что в нем несколько этажей. Схематично это будет выглядеть так:
Давайте создадим 3D-массив:
int [] [] [] cinemas = новый int [5] [5] [3];
Доступ к элементам приведенного выше трехмерного массива мы можем получить, как и раньше, через индекс, но теперь нам нужно ввести три координаты:
cinemas[3][2][1] = 1; // кинотеатр на втором этаже, третий ряд, четвертое место
В такой ситуации, если мы запросим cinemas[0][0].length
, то получим количество этажей.
Продемонстрируем простейшие манипуляции с элементами массива:
public class Array { public static void main(String[] args) { int[] a = new int[4]; a[0] = 17; //Инициализация элементов массива a[1] = 15; a[2] = 8; a[3] = 8; String[] s = {"October", "November", "December"}; /* Инициализацию и объявление можно применять параллельно*/ String[] s2 = new String[]{"Highload", "Today"}; /*Иногда инициализация и объявление могут применяться вместе с оператором new */ s2[0] = "Highload - "; //Изменяем первый элемент массива System.out.println(s2[0] + s2[1]); // Отображение в консоли "Highload - Today" a[2] = 5; // Компоненты массива - переменные System.out.println(a[2]); } }
Наиболее часто встречающаяся операция с массивами — поиск по элементу. Есть много алгоритмов, позволяющих ее решить. Например, можно выбрать наиболее легкий, но и самый медленный метод поиска – линейный:
public static int linearSearch(int[] array, int elementWanted) { for (int i = 0; i < array.length; i++) { if (array[i] == elementWanted) { return i; } } return -1; }
Если наш массив уже упорядочен, можем применить другой метод. Для поиска:
middleIndex
;Когда разыскиваемый элемент меньше «центрального элемента» мы забываем про правую часть массива, а иначе — про левую часть. Затем повторяем эти действия до обнаружения элемента или пока очередной отрезок не станет пустым. В том случае, если элемент не обнаружен, возвращается значение -1
:
public static int binarySearch(int[] array, int elementWanted) { int firstIndex = 0; int lastIndex = array.length - 1; // условие прекращения (элемент не представлен) while (firstIndex <= lastIndex) { int middleIndex = (firstIndex + lastIndex) / 2; // если центральный элемент - целевой элемент, возвращаем его индекс if (array[middleIndex] == elementWanted) { return middleIndex; } // когда центральный элемент в массиве меньше // переводим индекс в middle+1, не рассматривая первую часть else if (array[middleIndex] < elementWanted) { firstIndex = middleIndex + 1; } // если центральный элемент больше // переводим наш индекс в middle-1, не рассматривая первую часть else if (array[middleIndex] > elementWanted) { lastIndex = middleIndex - 1; } } return -1; }
Выполнять упорядочивание массива можно используя метод .sort()
класса Arrays
(не забываем в начале программы добавлять import java.util.Arrays;
):
int[] highload = { 24, 7, 23, 6765, 95, 33 }; Arrays.sort(highload); System.out.println(Arrays.toString(highload));// [7, 23, 24, 33, 95, 6765]
Более подробно о различных алгоритмах сортировки массивов можете почитать в статье «Методы сортировки и их реализация в Python». Несмотря на то, что мы писали в этой статье про Python, все алгоритмы актуальны и для Java.
Иногда может возникнуть необходимость преобразования массива к строке. Есть разные способы решения данной задачи. Например, обратиться к статическому методу join()
класса String
, который объединяет элементы массива. В этом примере элементы массива отделяются при помощи указанным параметром — разделителем:
String[] words = ["Highload", "Today"]; // Разделитель может быть пустой строкой String.join("", words); // "HighloadToday" String.join(", ", words); // "Highload, Today"
Наиболее часто используемые операции по работе с java-массивами:
Одним из самых удобных способов решения такого рода задач является использование класса Arrays пакета java.util. Рассмотрим на примере их реализацию:
class Main { public static void main(String[] args) { int[] test = {1, 5, 4, 3, 7}; //объявление и инициализация массива System.out.println(test); //попытка вывода нашего массива в консоль (результат 16-ричное число) System.out.println(Arrays.toString(test)); //выводим в консоль массив при помощи метода toString и радуемся правильному результату Arrays.sort(test, 0, 4); //сортировка массива от 0-й до 4-й ячейки System.out.println(Arrays.toString(test)); //выводим результат сортировки int keyArray = Arrays.binarySearch(test, 8); // поиск keyArray - т.е. числа 8 в отсортированном массиве, метод binarySearch выдает индекс искомого элемента System.out.println(keyArray); //выводим в консоль этот индекс System.out.println(Arrays.binarySearch(test, 0)); //пробуем найти элемент, отсутствующий в массиве и выводим результат в консоль } }
Выведет:
[I@1540e19d [1 , 5 , 4 , 3 , 7] [1, 3, 4, 5, 7] 3 -1
Теперь вы можете самостоятельно управлять в языке Java таким важным математическим инструментом. Если вы желаете закрепить полученные знания, рекомендуем вам посмотреть видео, в котором подробно разобран ряд задач, связанных с одномерными и многомерными массивами в Java:
Прокси (proxy), или прокси-сервер — это программа-посредник, которая обеспечивает соединение между пользователем и интернет-ресурсом. Принцип…
Согласитесь, было бы неплохо соединить в одно сайт и приложение для смартфона. Если вы еще…
Повсеместное распространение смартфонов привело к огромному спросу на мобильные игры и приложения. Миллиарды пользователей гаджетов…
В перечне популярных чат-ботов с искусственным интеллектом Google Bard (Gemini) еще не пользуется такой популярностью…
Скрипт (англ. — сценарий), — это небольшая программа, как правило, для веб-интерфейса, выполняющая определенную задачу.…
Дедлайн (от англ. deadline — «крайний срок») — это конечная дата стачи проекта или задачи…