JavaRush /Курсы /Java Syntax Pro /Двумерные массивы

Двумерные массивы

Java Syntax Pro
5 уровень , 4 лекция
Открыта

1. Двумерные массивы

И еще один интересный факт о массивах. Массивы бывают не только линейными, но и двумерными.

И что это значит, спросите вы?

А это значит, что ячейки массива можно представить не только в виде столбца (или строки), но и в виде прямоугольной таблицы.

int[][] имя = new int[ширина][высота];

Где имя — это имя переменной-массива, ширина — это ширина таблицы (в ячейках), а высота — это высота таблицы. Пример:

int[][] data = new int[2][5];
data[1][1] = 5;
Создаем двумерный массив: два столбца и 5 строк.
В ячейку (1,1) записываем 5.

Вот как это будет выглядеть в памяти:

Двумерные массивы

Кстати, для двумерных массивов можно тоже использовать быструю инициализацию:

// длины месяцев года поквартально
int[][] months = { {31, 28, 31}, {30, 31, 30}, {31, 31, 30}, {31, 30, 31} };

Есть очень много мест, где вам как программисту может понадобиться двумерный массив. Реализация практически любой настольной игры — это же готовый двумерный массив: «Шахматы», «Шашки», «Крестики-Нолики», «Морской бой»:

Двумерные массивы 2

Игровое поле «Шахмат» или «Морского боя» такое, что оно просто идеально ложится на двумерные массивы, только в качестве координат клеток нужно будет использовать только числа. Не «пешка e2 -> e4», а «пешка (4,1) -> (4,3)». Вам как программисту будет даже проще.


2. Расположение элементов в массивах: (x,y) или (y,x)

Тут, кстати, есть интересная дилемма:

Когда мы создаем массив new int[2][5]; у нас таблица «две строки и 5 столбцов» или все-таки «два столбца и 5 строк»? Другими словами, мы сначала задаем «ширину», а потом «высоту» или все-таки сначала «высоту», а потом — «ширину»? И, как говорится, тут не все так однозначно.

Начнем с вопроса: а как эта таблица реально хранится в памяти?

В самой памяти компьютера никаких таблиц нет: все байты памяти пронумерованы как 0, 1, 2, ... Это для нас таблица 2×5, а в памяти это просто 10 ячеек и все. Без разделения, где строки и где столбцы.

Аргумент в пользу гипотезы «ширина»-«высота».

Еще в школе всех учили, что из пары координат сначала указывается «x», а затем «y». И это не просто школьный стандарт — это вообще стандарт в математике. Против царицы наук, как говорится, не попрешь. Так что? Сначала «ширина», а затем «высота»?

Аргумент в пользу гипотезы «высота»- «ширина».

Тут тоже есть интересный аргумент и идет он из... быстрой инициализации двумерных массивов. Ведь если мы захотим инициализировать наш массив, напишем этот код как:

// Важная матрица с данными
int[][] matrix = { {1, 2, 3, 4, 5}, {1, 2, 3, 4, 5} };

Ничего не замечаете? А если так:

// Важная матрица с данными
int[][] matrix = {
  {1, 2, 3, 4, 5},
  {1, 2, 3, 4, 5}
};

Если мы напишем наши данные в коде построчно, то получим таблицу, у которой 2 строки и 5 столбцов.

Итоги

Что тут скажешь? Вам решать, как вам удобнее. Главное, чтобы все программисты, работающие над одним проектом, придерживались одного подхода.

Если вы будете работать над проектом, где много инициализированных двумерных массивов в коде, то скорее всего там все будут отталкиваться от быстрой инициализации данных и будет стандарт «высота»-«ширина».

Если же вам повезет попасть в проект, где много математики и работают с координатами (например, работа с игровыми движками), там скорее всего будут придерживаться подхода «ширина»-«высота»


3. Устройство двумерных массивов

А сейчас вы узнаете, как на самом деле устроены двумерные массивы. Готовы?

Двумерные массивы — это на самом деле массивы массивов!

Другими словами, если в случае с обычным массивом «переменная-массив хранит ссылку на контейнер, который хранит элементы массива». То в случае с двумерными массивами у нас ситуация немного взрывоопаснее: переменная-двумерный-массив хранит ссылку на контейнер, который хранит ссылки на одномерные массивы. Это лучше один раз увидеть, чем сто раз попробовать объяснить:

Устройство двумерных массивов

Слева у нас «переменная-двумерный-массив», которая хранит ссылку на «объект-двумерный массив». В середине у нас «объект двумерный массив», в ячейках которого хранятся ссылки на одномерные массивы — строки двумерного массива. Ну и справа вы видите четыре одномерных массива — строки нашего двумерного массива.

Это то, как на самом деле устроены двумерные массивы. И такой подход дает Java-программисту несколько преимуществ:

Во-первых, т.к. «контейнер контейнеров» хранит ссылки на «массивы-строки», мы можем очень быстро и просто менять строки местами. Чтобы получить доступ к «контейнеру контейнеров», нужно просто указать один индекс вместо двух. Пример:

int[][] data = new int[2][5];
int[] row1 = data[0];
int[] row2 = data[1];

Вот с помощью такого кода можно поменять строки местами:

// Важная матрица с данными
int[][] matrix = {
  {1, 2, 3, 4, 5},
  {5, 4, 3, 2, 1}
};

int[] tmp = matrix[0];
matrix[0] = matrix[1];
matrix[1] = tmp;
Двумерный массив





В matrix[0] у нас хранится ссылка на первую строку.
Меняем ссылки местами.

В итоге массив matrix выглядит так:
{
  {5, 4, 3, 2, 1},
  {1, 2, 3, 4, 5}
};

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



Комментарии (582)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Andrey Уровень 2
8 января 2026
До этого проходил https://stepik.org/lesson/296419/step/22?unit=278139 курс по питону. Гораздо круче обьяснение. Хотя работала маленькая команда. А тут какойто бред. Откуда нам знать такое. Показали ноготь а хотят в задачах руку.
Анна Клушкина Уровень 11
5 января 2026
⛏ В комментариях не менее интересно чем в самой лекции 👀
Dmitry Уровень 10
13 декабря 2025
На удивление быстро решил, минут за 15-20, это очень мотивирует, особенно после прошлой задачи, вот код, который получился: public static void main(String[] args) { MULTIPLICATION_TABLE = new int[10][10]; for(int i=0; i<MULTIPLICATION_TABLE.length; i++){ int a = i+1; for(int j=0; j<MULTIPLICATION_TABLE[i].length; j++){ MULTIPLICATION_TABLE[i][j]=(a*(j+1)); System.out.print(MULTIPLICATION_TABLE[i][j] + " "); } System.out.println(); } } } Вроде лаконично вышло, если вдруг есть какие то правки, то буду рад почитать!:)
d0vbnya Уровень 2
7 декабря 2025

public static void main(String[] args) {
        MULTIPLICATION_TABLE = new int[10][10];
        int num = 1;
        for (int i = 0; i < MULTIPLICATION_TABLE.length; i++)
        {
            for (int j = 0; j < MULTIPLICATION_TABLE[i].length; j++)
            {
                MULTIPLICATION_TABLE[i][j] = (i + 1) * (j + 1);
                System.out.print(MULTIPLICATION_TABLE[i][j] + " ");
            }
            System.out.println();
        }
Магомед Уровень 7
29 ноября 2025
MULTIPLICATION_TABLE = new int [10][10]; MULTIPLICATION_TABLE [0] =new int[] {1,2,3,4,5,6,7,8,9,10}; for ( int a = 0; a < 10;a++ ) { for ( int x = 0; x < 10; x++ ) { MULTIPLICATION_TABLE[a][x]= (MULTIPLICATION_TABLE[0][x] * (a + 1)); System.out.print( MULTIPLICATION_TABLE [a][x] + " "); } System.out.println(); } } } чуть позже до меня дошло , что можно написать проще, не отталкиваясь от первой строки, по формуле MULTIPLICATION_TABLE[a][x] = ( a +1) *( x + 1)
C0N5P1RACY Уровень 21
27 ноября 2025
Что то я не вижу тут комментария "РАБОТАЕМ!!"
Роман Зарубин Уровень 8
29 ноября 2025
РАБОТАЕМ !
C0N5P1RACY Уровень 21
30 ноября 2025
XD
SUNSHINE Уровень 14
24 ноября 2025
Подумал над тем, чтобы сделать задачку более универсальной к изменению размерности таблицы) Чтобы массив два раза не изменял одно и то же значение на то же значение - вынес за цикл элемент[0][0]. Т.к. таблица может быть не только квадратной, но и прямоугольной - отдельными циклами заполнил нулевую строку и нулевой столбец(насколько я понял из решения на сайте - это можно было сразу в заполнении массива сделать, но я не додумался) Что скажете, гуру ?) Есть замечания ?) public class Solution { public static int[][] MULTIPLICATION_TABLE; public static void main(String[] args) { MULTIPLICATION_TABLE = new int[10][10]; MULTIPLICATION_TABLE[0][0] = 1; for(int i = 1; i < MULTIPLICATION_TABLE.length; i++) MULTIPLICATION_TABLE[i][0] = i + 1; for(int i = 1; i < MULTIPLICATION_TABLE[0].length; i++) MULTIPLICATION_TABLE[0][i] = i + 1; for(int i = 1; i < MULTIPLICATION_TABLE.length; i++) for(int j = 1; j < MULTIPLICATION_TABLE[i].length; j++) MULTIPLICATION_TABLE[i][j]= MULTIPLICATION_TABLE[i][0] * MULTIPLICATION_TABLE[0][j]; for(int i = 0; i < MULTIPLICATION_TABLE.length; i++) { for(int j = 0; j < MULTIPLICATION_TABLE[i].length; j++) System.out.print(MULTIPLICATION_TABLE[i][j] + " "); System.out.println(); } } }
Alex Уровень 8
18 ноября 2025
Предлагаю свой код с использованием параметра для форматирования printf + "%4d" int[][] MULTIPLICATION_TABLE = new int[10][10]; for (int i = 1; i <= 10; i++) { for (int j = 1; j <=10; j++) { MULTIPLICATION_TABLE[i][j] = i * j; System.out.printf("%4d", MULTIPLICATION_TABLE[i][j]); } System.out.println(); }
techn0di Уровень 17
3 ноября 2025
Все гордятся коротким кодом, который у всех с первого раза зашел вот мой: MULTIPLICATION_TABLE = new int[10][10]; for (int i = 0; i < MULTIPLICATION_TABLE.length; i++) { for (int j = 0; j < MULTIPLICATION_TABLE[i].length; j++) { if (i == 0 && j == 0) { MULTIPLICATION_TABLE[i][j] = 1; } if (i == 0 && j != 0) { MULTIPLICATION_TABLE[i][j] = MULTIPLICATION_TABLE[i][j-1] + 1; } if (i != 0 && j == 0) { MULTIPLICATION_TABLE[i][j] = MULTIPLICATION_TABLE[i-1][j] + 1; } if (i != 0 && j != 0) { MULTIPLICATION_TABLE[i][j] = (i + 1) * (j + 1); } if (j == 9) { System.out.println(MULTIPLICATION_TABLE[i][j]); } else { System.out.print(MULTIPLICATION_TABLE[i][j] + " "); } } } Ребята, которые пришли из гуманитарных направлений, не сдавайтесь! все получится :)
Denis Skab Уровень 8
2 октября 2025
а почему не зделать в место пробела между числами "\t" так таблица красиво выглядит, самое интересное что в Java25 вы именно это и запрашиваете а тут это ошибка