Массивы
Часто на практике приходится работать с целыми наборами данных. Например для календаря нам нужен список названий месяцев, но как его хранить? Создавать 12 переменных и писать большое количество кода для работы с этими переменными? Это плохое решение, оно громоздкое, запутанное и неудобное. К счастью в языке Java есть отличная альтернатива - массивы.
Массив позволяет хранить целый набор данных определённого типа. По большому счёту массив можно представить себе как пронумерованный список или в более сложном случае - таблица. Массивы очень широко используются в приложениях и очень сильно упрощают обработку информации.
Одномерный массив
Одномерный массив представляет собой список однотипных элементов. На рисунке ниже приведён пример одномерного массива из 8 элементов:
В данном примере в качестве элементов массива выступают различные числа. Кроме этого, каждой ячейке массива соответствует свой индекс, по которому можно получить значение, записанное в ячейку. Обратите внимание что нумерация элементов массива начинается с нуля, это очень важный момент!
Общая форма объявления массива выглядит так:
тип_данных[] имя_массива = new тип_данных[размер_массива];
Напишем простую программу, которая по номеру месяца будет выводить его название:
В строке 8 инициализируется массив строк months размером в 12 элементов - ровно столько нам нужно для хранения всех названий месяцев:
String[] months = new String[12];
В строках с 9 по 20 в каждый элемент массива months записывается название месяца. Обращение к элементу идёт по его индексу в квадратных скобках - таким образом мы можем как записать данные в ячейку, так и прочитать. Важный момент - первый элемент имеет индекс 0, как я уже писал выше.
months[0] = "январь";
months[1] = "февраль";
months[2] = "март";
months[3] = "апрель";
months[4] = "май";
months[5] = "июнь";
months[6] = "июль";
months[7] = "август";
months[8] = "сентябрь";
months[9] = "октябрь";
months[10] = "ноябрь";
months[11] = "декабрь";
После того как массив заполнен элементами, программа просит пользователя ввести номер месяца и сохраняет его в переменную number:
Scanner input = new Scanner(System.in);
System.out.println("Введите номер месяца:");
int number = input.nextInt();
Далее в строке 26 программа выводит в консоль название месяца, которое достаёт из массива по индексу. Так как нумерация индексов идёт с нуля, то мы должны из number вычесть единицу, чтобы получить правильное название месяца. Например 5 месяц в году это май, но в массиве значение “май” хранится в элементе с индексом 4, поэтому когда пользователь введёт номер 5, мы должны вычесть из него 1 и получим 4:
System.out.println(months[number-1]);
В данном случае я не сделал проверку на корректность ввода данных, поэтому если пользователь введёт неправильное число, например 100, то приложение выдаст ошибку ArrayIndexOutOfBoundsException. Это значит что была попытка обратиться к несуществующему элементу массива.
Полный листинг программы:
package ru.akutepov.example1;
import java.util.Scanner;
public class MonthByNumber {
public static void main(String[] args) {
String[] months = new String[12];
months[0] = "январь";
months[1] = "февраль";
months[2] = "март";
months[3] = "апрель";
months[4] = "май";
months[5] = "июнь";
months[6] = "июль";
months[7] = "август";
months[8] = "сентябрь";
months[9] = "октябрь";
months[10] = "ноябрь";
months[11] = "декабрь";
Scanner input = new Scanner(System.in);
System.out.println("Введите номер месяца:");
int number = input.nextInt();
System.out.println(months[number-1]);
}
}
Данный пример выглядит довольно громоздко, но есть способ его упростить. Познакомимся с ещё одной формой инициализации массива в Java:
тип_данных[] имя_массива = {элемент0, элемент1, элемент2, ..., элементN} ;
Эта форма позволяет заполнять массив значениями сразу во время его инициализации, что сокращает количество кода.
Перепишем программу и посмотрим что получится:
Так гораздо лучше - код уже не выглядит таким громоздким, при этом логика осталась та же самая. В зависимости от ситуации можно использовать любую из форм инициализации массива.
Полный листинг программы:
package ru.akutepov.example2;
import java.util.Scanner;
public class MonthByNumber {
public static void main(String[] args) {
String[] months = {"январь", "февраль", "март", "апрель", "май", "июнь", "июль", "август", "сентябрь",
"октябрь", "ноябрь", "декабрь"};
Scanner input = new Scanner(System.in);
System.out.println("Введите номер месяца:");
int number = input.nextInt();
System.out.println(months[number - 1]);
}
}
Пример работы полученной программы:
Эту программу можно было бы написать без использования массива, например делать проверку номера месяца через оператор switch и выводить соответсвующее название. При этом решение с оператором switch тоже было бы вполне рабочим, но не таким красивым. Из этого следует вывод, что любую задачу можно решить несколькими способами и программист должен уметь выбрать оптимальное решение.
Многомерные массивы
В языке Java многомерные массивы представляют собой массивы массивов. Самый распространённый вид многомерных массивов - двумерные массивы.
Рассмотрим пример объявления такого массива:
int[][] a = new int[5][5];
В данном примере был проинициализирован двумерный массив a размером 5 на 5, который можно представить ввиде таблицы:
a[0][0] |
a[0][1] |
a[0][2] |
a[0][3] |
a[0][4] |
a[1][0] |
a[1][1] |
a[1][2] |
a[1][3] |
a[1][4] |
a[2][0] |
a[2][1] |
a[2][2] |
a[2][3] |
a[2][4] |
a[3][0] |
a[3][1] |
a[3][2] |
a[3][3] |
a[3][4] |
a[4][0] |
a[4][1] |
a[4][2] |
a[4][3] |
a[4][4] |
Если для доступа к элементу одномерного массива нужно указать один индекс, то для доступа к элементу двумерного массива указываются уже два индекса. Левый индекс это номер строки, правый индекс это номер столбца условной таблицы.
Для получения значения из опредённой ячейки нужно указывать 2 индекса, например a[3][1]. Если указать только 1 индекс, то будет получена целая строка из таблицы в виде одномерного массива. Например a[2] вернёт нам элементы 3-ей строки.
В Java допускаются и n-мерные массивы, вот общий синтаксис объявления таких массивов:
тип_данных[][]...[] имя_массива = new тип_данных[размер1][размер2]...[размерN];
Используются такие массивы крайне редко и их трудно изобразить графически, но смысл остаётся тот же.
Посмотрим на практическом примере как работать с двумерным массивом. Для этого усложним предыдущую задачу - вместе с названием месяца будем выводить количество дней в выбранном месяце:
Вместо одномерного массива у нас теперь двумерный массив размером 2 на 12. В первая строка массива - названия месяцев, вторая строка - информация о количестве дней в месяце.
String[][] months = {
{"январь", "февраль", "март", "апрель", "май", "июнь", "июль", "август", "сентябрь", "октябрь", "ноябрь", "декабрь"},
{"31 день", "28/29 дней", "31 день", "30 дней", "31 день", "30 дней", "31 день", "31 день", "30 дней", "31 день", "30 дней", "31 день"}
};
В строке 17 обращение к элементу массива теперь по 2 индексам - индекс строки и индекс столбца:
System.out.println(months[0][number - 1] + " - " + months[1][number - 1]);
Полный листинг программы:
package ru.akutepov.example3;
import java.util.Scanner;
public class MonthByNumber {
public static void main(String[] args) {
String[][] months = {
{"январь", "февраль", "март", "апрель", "май", "июнь", "июль", "август", "сентябрь", "октябрь", "ноябрь", "декабрь"},
{"31 день", "28/29 дней", "31 день", "30 дней", "31 день", "30 дней", "31 день", "31 день", "30 дней", "31 день", "30 дней", "31 день"}
};
Scanner input = new Scanner(System.in);
System.out.println("Введите номер месяца:");
int number = input.nextInt();
System.out.println(months[0][number - 1] + " - " + months[1][number - 1]);
}
}
Вот как теперь работает наша программа:
Получение длины массива
Часто бывает удобно программно узнать длину массива и Java предоставляет такую возможность. Для этого можно воспользоваться свойством length:
имя_массива.length
Это особенно удобно в циклах, когда нужно перебрать все элементы массива. Например выведем в столбик все названия месяцев:
В данном случае я задал для цикла условие i < months.length, таким образом, когда переменная i станет равно 12, цикл завершит свою работу. Последним из массива будет извлечён элемент с индексом 11 (помним что нумерация элементов начинается с 0).
Полный листинг программы:
package ru.akutepov.example4;
public class Months {
public static void main(String[] args) {
String[] months = {"январь", "февраль", "март", "апрель", "май", "июнь", "июль", "август", "сентябрь", "октябрь", "ноябрь", "декабрь"};
for (int i = 0; i < months.length; i++) {
System.out.println(months[i]);
}
}
}
Ещё удобнее перебирать элементы массива с помощью цикла foreach:
Такая запись выглядит лаконичнее и легче читается. Смысл при этом остаётся тот же - цикл перебирает все элементы массива, но теперь каждый элемент записывается в переменную month, которая в теле цикла выводится в консоль.
Полный листинг программы:
package ru.akutepov.example5;
public class Months {
public static void main(String[] args) {
String[] months = {"январь", "февраль", "март", "апрель", "май", "июнь", "июль", "август", "сентябрь", "октябрь", "ноябрь", "декабрь"};
for (String month : months) {
System.out.println(month);
}
}
}
Результат работы программы выглядит следующим образом:
Домашнее задание
- Дан одномерный массив размером 10 элементов. Заполнить массив целыми числами и найти максимальное и минимальные числа в массиве. Вывести результат на экран.
- Дан одномерный массив размером 10 элементов. Заполнить массив целыми числами и определить являются ли элементы массива возрастающей последовательностью.
- Дан двумерный массив размером 5 на 10 элементов. Заполнить его произвольными значениями. Все элементы больше 5 заменить на 0.