Многомерные массивы в Java
Работа с двумерными и многомерными массивами в Java, включая зубчатые массивы.
В Java нет отдельного типа «двумерный массив». Есть массивы массивов — int[][] представляет собой массив, элементами которого являются int[]. Синтаксис достаточно лаконичен и выглядит как встроенная таблица, и в большинстве случаев можно использовать его именно так. Если вы только знакомитесь с основами, начните с массивов Java; эта страница строится на тех же понятиях, добавляя одно измерение за другим.
На этой странице рассматриваются объявление и выделение памяти для двумерных массивов, чтение и запись ячеек, получение количества строк и столбцов, итерирование, зубчатые (нерямоугольные) массивы и редкий случай с массивами более высоких измерений.
Объявление двумерного массива
Добавьте ещё одну пару скобок к типу:
int[][] grid;
String[][] board;Выделите память, указав два размера — сначала строки, затем столбцы:
int[][] grid = new int[3][4]; // 3 rows, 4 columns, all zeroИли используйте вложенный литерал:
int[][] grid = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};Внешние фигурные скобки содержат три подмассива, каждый длиной 4.
Доступ к элементам
Два индекса: сначала строка, затем столбец.
int[][] grid = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
System.out.println(grid[0][0]); // 1
System.out.println(grid[2][1]); // 8
grid[1][1] = 50; // replace 5 with 50grid[0] сам по себе — это первая строка, то есть int[] длиной 3. Это ключевое понятие: один индекс даёт строку, два индекса — ячейку.
length для строк и столбцов
grid.length — количество строк. grid[r].length — количество столбцов в строке r:
int rows = grid.length;
int cols = grid[0].length; // assuming row 0 existsНет никакого grid.cols на верхнем уровне, потому что Java не предполагает, что все строки имеют одинаковую длину — см. зубчатые массивы ниже.
Итерирование
Стандартный двойной цикл for:
for (int r = 0; r < grid.length; r++) {
for (int c = 0; c < grid[r].length; c++) {
System.out.print(grid[r][c] + " ");
}
System.out.println();
}Или с расширенным for, рассматривая каждую строку как int[]:
for (int[] row : grid) {
for (int cell : row) {
System.out.print(cell + " ");
}
System.out.println();
}Используйте расширенную форму, когда координаты не нужны, и классическую форму — когда они нужны.
Зубчатые массивы
Внутренние массивы не обязаны иметь одинаковую длину. Массив массивов в Java может быть зубчатым — каждая строка задаётся независимо:
int[][] triangle = new int[4][]; // 4 rows, columns unspecified
triangle[0] = new int[]{1};
triangle[1] = new int[]{1, 2};
triangle[2] = new int[]{1, 2, 3};
triangle[3] = new int[]{1, 2, 3, 4};new int[4][] каждая строка равна null, пока вы не присвоите ей массив. Обращение к triangle[0][0] до triangle[0] = ... вызовет NullPointerException, а не ArrayIndexOutOfBoundsException. При использовании полностью размерной формы new int[3][4] все строки создаются и заполняются нулями автоматически.Или с помощью литерала:
int[][] triangle = {
{1},
{1, 2},
{1, 2, 3},
{1, 2, 3, 4}
};Итерирование работает точно так же — вы запрашиваете .length у каждой строки:
for (int r = 0; r < triangle.length; r++) {
for (int c = 0; c < triangle[r].length; c++) {
System.out.print(triangle[r][c] + " ");
}
System.out.println();
}Вот почему int[][] называется «массивом массивов», а не истинной матрицей: язык не обязывает каждую строку иметь одинаковую ширину.
Более высокие измерения
Паттерн расширяется. int[][][] — это массив массивов массивов, полезный для трёхмерной сетки, стека матриц, RGB-изображения (высота × ширина × 3):
int[][][] cube = new int[2][3][4]; // 2 × 3 × 4
cube[0][1][2] = 99;На практике всё, что выходит за пределы двух измерений, редко встречается в идиоматичном Java-коде — в таких случаях класс с именованными полями почти всегда нагляднее.
Практический пример
Что дальше
Вы теперь знаете массивы в одном и нескольких измерениях. Далее мы рассмотрим повседневные операции с массивами — получение длины, заполнение, поиск, копирование — и вспомогательные инструменты стандартной библиотеки, превращающие большинство из них в однострочники.