Материал предоставлен https://it.rfei.ru

Многомерные массивы

Поскольку элемент массива может быть ссылкой на объект, а массивы являются объектами, то элементы массива могут сами ссылаться на другие массивы. В Java массив массивов может быть определен следующим образом:

<тип_элемента>[][]...[] <имя_массива>;

или

<тип_элемента> <имя_массива>[][]...[];

Фактически последовательность пар квадратных скобок [ ], указывающая количество, может располагаться или после <типа элемента>, или после <имени массива>. Массивы массивов также иногда называют многомерными массивами. Следующие объявления эквивалентны.

int[][] mXnArray;      // 2-мерный массив
int[]   mXnArray[];    // 2-мерный массив
int     mXnArray[][];  // 2-мерный массив

Обычно объединяют объявление с созданием многомерного массива.

int[][] mXnArray = new int[4][5];    // 4 x 5 матрица целых чисел

Предыдущее объявление создает массив mXnArray из четырех элементов, причем каждый элемент массива является массивом (строкой) из пяти целых значений. Идея строк и столбцов часто применяется в описании 2-мерного массива, который, в свою очередь, часто называют матрицей. Но подобная интерпретация не навязывается языком программирования Java.

Каждая строка предыдущей матрицы обозначается mXnArray[i], 0 ≤ i < 4. К каждому элементу в i-й строке mXnArray [i] можно обращаться mXnArray [i][j], где 0 ≤ j < 5. Количество строк задается mXnArray.length, в нашем случае 4, и количество значений в i-й строке задается mXnArray[i].length, в нашем случае 5 для всех строк, где 0 ≤ i < 4.

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

double[][] identityMatrix = {
        { 1.0, 0.0, 0.0, 0.0 }, // 1. строка
        { 0.0, 1.0, 0.0, 0.0 }, // 2. строка
        { 0.0, 0.0, 1.0, 0.0 }, // 3. строка
        { 0.0, 0.0, 0.0, 1.0 }  // 4. строка
}; // 4 x 4 вещественная матрица

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

Pizza[][] pizzaGalore = {
        { new Pizza(), null, new Pizza() },    // 1. строка в массиве из 3 элементов
        { null, new Pizza() },                 // 2. строка в массиве из 2 элементов
        new Pizza[1],                          // 3. строка в массиве из 1 элементов
        { },                                   // 4. строка в массиве из 0 элементов
        null                                   // 5. Строка пока не создана
};

Если многомерные массивы создаются оператором new, то длину глубоко вложенных массивов можно опустить. В таком случае эти массивы остаются несозданными. Например, массив массивов, представляющий комнаты на этажах в гостиницах на улицах города может быть типа HotelRoom[][][][]. Соответственно слева направо квадратные скобки представляют индексы для улицы, отеля, этажа и комнаты. Такой 4-мерный массив массивов может создаваться по частям, начиная с самого левого измерения и до правого.

HotelRoom[][][][] rooms = new HotelRoom[10][5][][];  // Только улицы и отели

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

rooms[0][0]       = new HotelRoom[3][]; // 3 этажа в 1-й гостинице на 1-й улице
rooms[0][0][0]    = new HotelRoom[8];   // 8 комнат на 1-м этаже в этой гостинице
rooms[0][0][0][0] = new HotelRoom();    // Инициализируем 1-ю комнату на этом этаже.

В следующем коде создается матрица, в которой в первой строке содержится один элемент, во второй строке — два элемента, а в третьей строке содержится три элемента. Обратите внимание, что внешний массив создается первым. Массив второго уровня создается в цикле, который заполняет массив построчно. Элементы массива будут неявно инициализированы значением по умолчанию типа double(0.0D). На рис. 4.1 изображена матрица элементов, которые были явно инициализированы.

double[][] matrix = new double[3][];      // без строк
for (int i = 0; i < matrix.length; ++i)
   matrix[i] = new double[i + 1];         // создание строки

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

double[][] matrix2 = {
        { 0.0 },                  // 1 строка
        { 0.0, 0.0 },             // 2 строка
        { 0.0, 0.0, 0.0 }         // 3 строка

};

double[][] matrix3 = new double[][]{
        { 0.0 },

        { 0.0, 0.0 },

        { 0.0, 0.0, 0.0 }

};

Тип переменной matrixdouble[][] (т.е. двумерный массив значений типа double). Типом переменной matrix[i](0 ≤ i < matrix.length) является double[] (т.е. одномерный массив значений типа double). Типом переменной matrix[i][j] (0 ≤ i < matrix.length и 0 ≤ j < matrix[i].length) является double (т.е. простая переменная типа double).

Рис. 4.1. Массив массивов

Вложенные циклы естественным образом подходят для управления многомерными массивами. В примере 4.3 объявлена и создана в строке (1) прямоугольная матрица 4x3 типа int. В программе происходит поиск минимального значения в матрице. Внешний цикл в строке (2) проходит по строкам mXnArray[i], 0 ≤ i < mXnArray.length, внутренний цикл в строке (3) проходит по очереди по элементам каждой строки mXnArray[i][j], 0 ≤ j < mXnArray[i].length). Внешний цикл выполняется mXnArray.length раз или 4 раза, внутренний цикл выполняется (mXnArray.length) x (mXnArray[i].length) раз или 12, потому что все строки имеют одинаковую длину, равную 3.

Пример 4.3. Применение многомерных массивов

class MultiArrays {

    public static void main(String[] args) {
        // Объявление и создание матрицы M X N
        int[][] mXnArray = {                                           // (1)
                { 16, 7, 12 }, // 1. row
                { 9, 20, 18 }, // 2. row
                { 14, 11, 5 }, // 3. row
                { 8, 5, 10 }   // 4. row
        }; // Матрица 4 x 3

        // Поиск минимального значения в матрице M X N
        int min = mXnArray[0][0];
        for (int i = 0; i < mXnArray.length; ++i)                      // (2)
            // Поиск минимума в mXnArray[i], т.е. в строке с индексом i.
            for (int j = 0; j < mXnArray[i].length; ++j)               // (3)
                min = Math.min(min, mXnArray[i][j]);
        System.out.println("Minimum value: " + min);
    }
}

Вывод программы:

Minimum value: 5
Инициализация и использование массивовКлассы и методы