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
в моєму коді все працює коректно) в ідеї перевірено) платформа дуже чутлива до рішень, що відрізняються і не завжди приймає робочий код)
Dmytro Рівень 26
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.
Beisik Рівень 25
14 вересня 2022
зробив за годину.Сидів радів що зробив все сам і ще й так коротко ,прочитав коментарі і побачив що можна ще коротше((.Ну та добре вже =DD
Roma Chernesh Рівень 16
5 грудня 2022
моя повага! Бо я не витримав і відповідь глянув
Pan Vitali Moroz Рівень 51
10 вересня 2022
якщо дового дивитися на масив то масив подивиться на тебе :о