Взяв массивы Java в другое измерение

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 для массивов примитивов

  • Для создания множества примитивов используется байт -код anewarray. Это требует аргумента, который указывает тип примитива, который будет хранить массив. Каждый элемент нового массива инициализируется к начальному значению по умолчанию для типа элемента типа массива. Вот почему мы не получаем ошибку компилятора при просьбе значения в локальном массиве примитивов, которые не были явно инициализированы.
  • Bytecode для массивов объектов

  • Anewarray Bytecode используется для создания одномерного массива ссылок на объекты. Это требует аргумента, который является индексом в постоянный пул времени выполнения, который определяет тип объекта, который будет удерживать массив. Этот байт -код также можно использовать для создания первого измерения многомерного массива. Опять же, все элементы будут содержать NULL, если не будет использован код инициализатора массива.
  • Bytecode для многомерных массивов

  • Multi-Anewarray Bytecode можно использовать для создания многомерного массива объектов. Как и Anewarray, он использует индекс в постоянный пул времени выполнения, чтобы определить тип объектов, которые будет удерживать массив (или нулевой). Кроме того, он также имеет количество для количества измерений, которые будет иметь массив, и набор значений для размера каждого измерения массива. Примечание, что этот байт -код не используется для многомерных массивов примитивов (поскольку в постоянном пуле нет типа). Для них массив построен с использованием комбинации anewarray и newarray. Для рваных массивов объектов Multianewarray может быть объединен с Anewarray, или весь массив может быть создан с использованием anewarray. Компилятор Javac определит наиболее эффективный подход.
  • Соображения производительности с многомерными массивами

    Будьте осторожны с тем, как вы используете многомерные массивы, так как простые изменения могут значительно повлиять на производительность. Например, зацикливание через двухмерный массив:

    инт[][] 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

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *