JavaRush /Курси /Java Syntax Zero /Двовимірні масиви

Двовимірні масиви

Java Syntax Zero
Рівень 6 , Лекція 5
Відкрита

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}
};

Якщо ви звертаєтеся до комірки двовимірного масиву, але після імені масиву вказуєте тільки один індекс, ви таким чином звернетеся до контейнера контейнерів, у комірках якого зберігаються посилання на звичайні одновимірні масиви.


Коментарі (28)
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ
Іван Рівень 8
17 листопада 2024
MULTIPLICATION_TABLE = [i - 1][j - 1] = i * j; спочатку написав так і не розумів, що не так я зробив у коді😀
ivan Рівень 10
20 червня 2024
Перший захід: не розібрався з умовами й ініціалізував через дужки { }. 😶 зайняло багато часу написати код, компілятор лаявся... Другий захід: перечитав умови, лекцію, коментарі. Зрозумів шо не туди думка йде, переписав за декілька хвилин й здав з першого разу😊
Єлизавета Рівень 51
30 квітня 2024
Моє рішення. В Ідеї все працює ідеально) на сайті не хоче приймати) та головне - результат) int[][] MULTIPLICATION_TABLE = new int[10][10]; for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { MULTIPLICATION_TABLE[i][j] = (j + 1) * (i + 1); System.out.print(MULTIPLICATION_TABLE[i][j]); System.out.print(" "); } System.out.println(); }
Volodymyr Рівень 7
2 травня 2024
тут int[][] MULTIPLICATION_TABLE = new int[10][10]; приберіть int[][] і все запрацює)
Єлизавета Рівень 51
5 травня 2024
в моєму коді все працює коректно) в ідеї перевірено) платформа дуже чутлива до рішень, що відрізняються і не завжди приймає робочий код)
Dmytrii Рівень 65
7 червня 2024
массив был задан ранее перед мейном, а ты снова его объявляешь. зачем?
Гаркін Рівень 14
17 лютого 2024
Попередження для завдання "Таблиця множення". Якщо Ви будет поділяти одинарні значення двома пробілами (для краси), то при перевірці видасть помилку.
Михайло Рівень 9 Expert
5 січня 2024
Нотатки: для вирішення проблеми мені було зручніше користуватися уявленням "вертикаль-горизонталь". Двох циклів тут більше ніж достатньо. Один починається з нуля, інший з одиниці. Далі пошукати математичні закономірності (Розгляньте ситуації: поверх 0, елемент 0 --> 1; поверх 0, елемент 1 --> 2; ... ; поверх 0, елемент 9 --> 10). Наснаги!
Ivan Kravets Рівень 22
10 грудня 2023
3 хвилини)))))))))
Vitalii KK Рівень 9
18 жовтня 2023
перед тим як почати задачу почитав моменти. все думав в чому підвох. за 2хв написав пару рядків і все завелось. ну, все. завтра йду на сенйора )))
Unfo Рівень 23
7 грудня 2022
[i-1] [j-1] це для відліку лічильника коректного? не зовсім розумію поки що напевне. буду вдячний за пояснення
Vitalii Рівень 11
31 липня 2023
порядок елементів в масивах рахуємо з 0-ля. а в таблиці множення рахуємо з 1-ці. Відповідно щоб наліпити сову на кульку - віднімаємо скрізь по 1.
hidden #3143523 Рівень 25
14 вересня 2022
зробив за годину.Сидів радів що зробив все сам і ще й так коротко ,прочитав коментарі і побачив що можна ще коротше((.Ну та добре вже =DD
Roma Chernesh Рівень 16
5 грудня 2022
моя повага! Бо я не витримав і відповідь глянув
Pan Vitali Moroz Рівень 51
10 вересня 2022
якщо дового дивитися на масив то масив подивиться на тебе :о