Java, наряду со многими другими языками программирования, включает в себя концепцию массивов. Массив — это объект, который содержит ряд переменных. Поскольку массив сам по себе является объектом, переменные в массиве также могут быть массивами, что приводит нас к идее многомерных массивов.
Что такое многомерный массив в Java?
Есть несколько способов определения и заполнения многомерных массивов на Java.
Объявление многомерного массива
Во -первых, вы можете объявить переменную массива, например:
инт[][] ИИ;
Int int aai[][];
Как вы можете видеть, положение квадратных кронштейнов (используемых для указания массива) может быть размещено после типа массива или после имени переменной. Я предпочитаю поставить кронштейны после типа массива, чтобы вся информация типа была в одном месте.
Смешивание позиций кронштейна
Также возможно смешать их позиционирование:
инт[] ай[];
Это не рекомендуется, так как это делает структуру массива труднее для понимания с первого взгляда. Этот пример делает это мучительно очевидным:
инт[][] х[][]y[][][]Z.[];
Это эквивалентно (но не очевидно) для отдельных определений:
инт[][][][] x;
инт[][][][][] y;
инт[][][] z;
В этих примерах мы просто объявляем переменные, которые можно использовать для ссылки на массив, но массивы не создаются. Локальные переменные подлежат определенному назначению; Если вы объявите локальную переменную, вы должны установить его значение на что -то. Если вы используете эти локальные переменные, не присваивая их массиву, компилятор сообщит, что X, Y и Z, возможно, не были инициализированы.
Создание многомерного массива
Есть два способа создать многомерный массив (как и для одномерных массивов).
Во -первых, мы можем использовать инициализатор массива. Например:
инт[][] aiv = {{1, 2}, {3, 4},};
Здесь мы определяем двухмерный массив и даем первый массив значения 1 и 2, а второй массив-значения 3 и 4. Я намеренно включил запятую после второго набора скобок, так как это допустимый синтаксис, даже если нет третьего набора значений (эта запятая-необязательно). Размеры массива определяются компилятором из указанных значений. В этом примере будет создан массив 2 × 2.
Второй способ — экземпляр массива с явными размерами:
инт[][] aie = new Int[2][2];
Опять же, у нас есть массив 2 × 2, но не вкладывая в него определенные значения.
Значения по умолчанию в массивах
Мы также должны помнить, что массив — это объект в Java, поэтому мы используем новый оператор. Почему это важно? Как локальная переменная, мы уже знаем, что если мы не присваиваем значение нашей ссылке на массив, код не будет компилироваться. Теперь у нас есть ссылка, но что произойдет, если мы попытаемся распечатать первый элемент первого массива? Потому что мы создали создание новых объектов массива, значение AIE[0][0] Будет 0 (мы поймем, почему позже). Если бы у нас был двухмерный массив струн, значение было бы нулевым. Несмотря на то, что это локальная переменная, в массиве, который мы создаем, есть значения по умолчанию, хранящиеся в нем.
Понимание зубчатых массивов
Одна из ключевых вещей, которые можно понять о многомерных массивах на Java, заключается в том, что они могут быть развратными (или зазубренными, в зависимости от того, кто их описывает). Это отличается от языков, таких как C (синтаксис которой в значительной степени основан на Java), который имеет прямоугольные массивы.
Давайте посмотрим, что это значит для вас как для разработчика.
Мы повторно используем один из наших предыдущих примеров:
инт[][] aiv = {{1, 2}, {3, 4}};
Этот массив реализован как массив ссылок на массивы, как показано на диаграмме.
По сути, есть три массива: один для сохранения значений 1 и 2, один для сохранения значений 3 и 4, и один для сохранения ссылок на эти два массива. Поскольку ссылки на массивы независимы, мы не обязаны делать их одинакового размера.
Мы можем изменить второй массив, чтобы содержать три значения:
инт[][] aiv = {{1, 2}, {3, 4, 5}};
Хранение массива теперь выглядит так:
Если бы у нас был трехмерный массив, каждый элемент во втором измерении стал бы ссылкой на массив. Например:
int aiv[][][] = {{кибербезопасность, {2,3}}, {{4,5}, {6,7}, {8,9}}};
Массивовое хранилище будет выглядеть следующим образом:
Если бы мы распечатали значение AIV[1][0][1]мы получили бы 5.
Понимание байткодов JVM для создания массива
Если мы копаем немного глубже и посмотрим, как JVM обрабатывает массив, мы обнаружим, что используются три байткода, в зависимости от того, какой тип массива у нас есть.
Bytecode для массивов примитивов
Bytecode для массивов объектов
Bytecode для многомерных массивов
Соображения производительности с многомерными массивами
Будьте осторожны с тем, как вы используете многомерные массивы, так как простые изменения могут значительно повлиять на производительность. Например, зацикливание через двухмерный массив:
инт[][] aiv = {{1,2,3,4,5}, {6,7,8,9,10}, {11,12,13,14,15}};
для (int x = 0; x <3; x ++)
для (int y = 0; y <5; y ++)
AIV[x][y] = AIV[x][y] + 1;
для (int y = 0; y <5; y ++)
для (int x = 0; x <3; x ++)
AIV[x][y] = AIV[x][y] + 1;
Первая версия петли будет гораздо более эффективной, чем вторая. Причиной этого является структура многомерного массива, который мы видели ранее. Вторая версия продолжает переключаться между массивными ссылками на доступ к отдельным элементам, с связанными накладными расходами. Первая версия поддерживает ссылку на массив и проходит через все объекты, хранящиеся в нем.
Проценсорные различия в производительности
Я запустил аналогичный эталон на своем MacBook, используя 2000 массивов, каждый с 2000 элементами и повторил петлю тысячу раз. Первая версия петли была завершена через 620 мс, а вторая — 4200 мс. Это почти в семь раз медленнее.
Заключительные мысли
Многомерные массивы являются фундаментальной особенностью на языке Java и очень полезны, где размер измерений известен во время компиляции. Надеемся, что теперь вы лучше понимаете, как они работают и как эффективно использовать их в вашем коде.
Trending Stories youtube.com/thenewstack Tech движется быстро, не пропустите эпизод. Подпишитесь на наш канал YouTube, чтобы транслировать все наши подкасты, интервью, демонстрации и многое другое. Группа подпишитесь с эскизом. Саймон Риттер — заместитель технического директора Азула. Саймон присоединился к Sun Microsystems в 1996 году и провел время, работая как в разработке Java, так и в консультации. Он представляет Java Technologies разработчикам с 1999 года, сосредоточившись на основной платформе Java … Подробнее от Simon Ritter