Автор: Widowmaker1984

Вопрос 23 (многомерные массивы)

"Какие виды массивов вы знаете?"

1. В Java два вида массивов: одномерные и многомерные. Последние в Java фактически представляют из себя массивы массивов.

2. Для создания многомерных массивов используются дополнительные скобки:

int[][] a = {
{ 1, 2, 3 },
{ 4, 5, 6 }
}

2.1. Также массив может создаваться ключевым словом new:

// трехмерный массив фиксированной длины
int[][][] b = new int[2][4][4];

скрытый текст3. Размер двумерного массива измеряется интересным способом. Длина массива определяется по его первой размерности, то есть вычисляется количество рядов. Чтобы узнать количество столбцов в ряду, надо указать ряд, а затем вычислить у него количество столбцов.

// число колонок у третьего ряда
System.out.println(matrix[2].length);

4. Допустим, вы хотите представить таблицу умножения в виде многомерного массива:
int[][] multiplicationTable = new int[10][10];

В некоторых языках такой массив создается в виде единого блока из 100 значений int. Java поступает иначе. Эта строка кода выполняет три действия:

- Объявляет переменную с именем multiplicationTable, которая содержит ссылку на массив ссылок, которые в свою очередь будут указывать на массивы int.
- Создает массив из 10 элементов (первый индекс), который будет содержать ссылки на 10 одномерных массивов int. Отсюда собственно и понятие – массив массивов.
- На этой стадии создания массив ссылок заполняется значениями по умолчанию, то есть значениями null.
- Создает еще 10 массивов, каждый из которых в свою очередь является массивом из 10 элементов int.
- Присваивает ссылки на каждый из этих 10 новых массивов элементам массива, созданного на втором шаге. По умолчанию каждый элемент int каждого из этих 10 новых массивов получает значение 0.

4.1. Другими словами, представленную выше строку кода, можно записать так:

int[][] multiplicationTable = new int[10][]; // первый индекс содержит ссылки на массивы int
for (int i = 0; i < 10; i++)
multiplicationTable[i] = new int[10]; // создаем 10 массивов int

4.2. Очень важно понять, что хотя каждый из массивов с элементами int, располагаются в памяти непрерывным куском, но где и как расположены каждый из них самих определяет виртуальная машина Java. Исходя из этого есть рекомендация, что наружные (левые) размерности массива лучше делать меньше, а самые больше размерности внутри (правее), поскольку это, во-первых, уменьшит фрагментацию памяти, а во вторых потребует гораздо меньше памяти для размещения массива.

4.2.1. Возьмем к примеру вот такие два определения двумерных массивов:

int[][] a = new int[10][1000];
int[][] b = new int[1000][10];

В случае массива a, количество порождаемых в памяти объектов равно 11, а в случае массива b1001. Создание и обслуживание каждого объекта в памяти виртуальной машины имеет свои накладные расходы, так как виртуальная машина считает ссылки для каждого объекта, хранит его атрибуты и т.д. и т.п. Таким образом массив b может занимать в памяти в полтора, а то и в два раза больше места чем массив a.

5. При работе с многомерными массивами в Java очень важно понять, что первые индексы многомерных массивов содержат только массивы ссылок, и только последний (самый правый) индекс содержит непосредственно элемент данных типа объявленного для массива.

5.1. То есть в Java можно объявить и более чем двумерные массивы. Например:

int[][][] dim3D;

И тут важно понимать, что первый индекс данного массива, содержит массив ссылок, на второй индекс данного массива, который в свою очередь тоже содержит массив ссылок на массивы значений int. То есть если в данном случае вывести на консоль значение int[1][1], получим адрес ссылки. И только по полному индексу int[1][1][1] сможем получить значение элемента массива типа int.

5.2. Нижеприведенный код не вызовет ошибки компиляции, но вызовет ошибку во время исполнения: NullPointerException.

int[][] multiplicationTable = new int[10][];
multiplicationTable[0][0] = 10; // ошибка во время исполнения

Это происходит потому, что не был создан объект, в данном случае массив int-ов. То есть создан массив хранящий ссылки на массивы int-ов, но сами эти массивы еще не создны, поэтому обращение к несуществующему объекту вызывает ошибку. Это можно исправить следующим кодом:

int[][] multiplicationTable = new int[10][];
multiplicationTable[0] = new int [10];
multiplicationTable[0][0] = 10; // нет ошибки

5.3. Если создаете многомерные массивы, необязательно указывать все измерения массива – важно задать только крайнее слева измерение или измерения. Например, разрешены такие строки:

float[][][] globalTemperatureData = new float[360][][];
float[][][] globalTemperatureData = new float[360][180][];

Но такие варианты ошибочны:

float[][][] globalTemperatureData = new float[360][][100]; // Ошибка!
float[][][] globalTemperatureData = new float[][180][100]; // Ошибка!

Комментарии


Лучшее   Правила сайта   Вход   Регистрация   Восстановление пароля

Материалы сайта предназначены для лиц старше 16 лет (16+)