JavaRush /Курси /JAVA 25 SELF /Зубчасті масиви (Jagged Arrays)

Зубчасті масиви (Jagged Arrays)

JAVA 25 SELF
Рівень 7 , Лекція 4
Відкрита

1. Зубчасті масиви відрізняються від двовимірних

Отже, ми дійшли до теми, яку часто називають «зубчастими масивами» — англійською — jagged arrays. На відміну від двовимірних масивів, зубчасті масиви дозволяють зберігати рядки різної довжини. Це можна уявити як комплекс будівель, кожна з яких має свою кількість квартир: в одній будівлі 5 квартир, в іншій — 20, а у третій — лише одна.

Зубчастий масив — масив, у якому кожен елемент — теж масив, причому вкладені масиви (їх ще називають «підмасивами») можуть мати різну довжину.

Головна відмінність:

  • У двовимірному масиві кожен «рядок» (і кожен «стовпець») має однакову кількість елементів. Приклад: int[][] grid = new int[3][5]; — у нас завжди 3 рядки по 5 елементів.
  • У зубчастому масиві кожен рядок може мати різну довжину. Приклад: int[][] jagged = new int[3][]; — а вже потім ми кожен рядок (підмасив) ініціалізуємо по‑своєму.

Ось як це виглядає візуально:

Двовимірний масив (3x3):
┌───┬───┬───┐
│ 1 │ 2 │ 3 │
├───┼───┼───┤
│ 4 │ 5 │ 6 │
├───┼───┼───┤
│ 7 │ 8 │ 9 │
└───┴───┴───┘

Зубчастий масив (різні довжини):
┌───┬───┐
│ 1 │ 2 │
├───┼───┼───┬───┐
│ 3 │ 4 │ 5 │ 6 │
├───┼───┴───┴───┘
│ 7 │
└───┘

2. Синтаксис оголошення та ініціалізації зубчастого масиву

Оголошення зубчастого масиву не складніше за оголошення інших масивів. Лякатися подвійних квадратних дужок не варто:


int[][] jaggedArray = new int[3][];
Оголошення зубчастого масиву: зовнішній розмір задано, внутрішні масиви ще не створені

Це означає, що маємо масив із 3 елементів, і кожен із них — також масив типу int. Поки що внутрішні масиви не створені. Для кращого розуміння розгляньмо детальніше.

Покрокова ініціалізація зубчастого масиву

Крок 1 — створення основного (зовнішнього) масиву:

int[][] jaggedArray = new int[3][];

Тепер у нас є 3 «рядки», але всі вони поки що дорівнюють null.

Крок 2 — створення й заповнення внутрішніх масивів (підмасивів):
Наприклад, нехай перший рядок буде довжиною 2, другий — 4, третій — 3:

jaggedArray[0] = new int[2]; // 2 елементи у першому рядку
jaggedArray[1] = new int[4]; // 4 елементи у другому рядку
jaggedArray[2] = new int[3]; // 3 елементи у третьому рядку

Крок 3 — заповнення значеннями:
Внутрішні масиви — це звичайні масиви. Наприклад:

jaggedArray[0][0] = 1;
jaggedArray[0][1] = 2;

jaggedArray[1][0] = 3;
jaggedArray[1][1] = 4;
jaggedArray[1][2] = 5;
jaggedArray[1][3] = 6;

jaggedArray[2][0] = 7;
jaggedArray[2][1] = 8;
jaggedArray[2][2] = 9;

Скорочена ініціалізація зубчастого масиву

Можна створити й заповнити зубчастий масив одразу, якщо ви знаєте значення заздалегідь:

int[][] jaggedArray = new int[][]
{
    new int[] { 1, 2 },
    new int[] { 3, 4, 5, 6 },
    new int[] { 7, 8, 9 }
};

Або трохи коротше, опускаючи тип внутрішніх масивів:

int[][] jaggedArray = 
{
    { 1, 2 },
    { 3, 4, 5, 6 },
    { 7, 8, 9 }
};

3. Перебирання та робота із зубчастими масивами

Ітерувати зубчастий масив не складніше, ніж двовимірний: зовнішній цикл проходить рядками, а внутрішній — елементами рядка (їхня довжина може різнитися):

for (int i = 0; i < jaggedArray.length; i++) 
{
    System.out.println("Рядок " + i + ":");
    for (int j = 0; j < jaggedArray[i].length; j++) 
    {
        System.out.print(jaggedArray[i][j] + " ");
    }
    System.out.println();
}

Результат на екрані:

Рядок 0:
1 2 
Рядок 1:
3 4 5 6 
Рядок 2:
7 8 9 

Можна використати for-each, щоб не відстежувати індекси:

for (int[] row : jaggedArray) 
{
    for (int value : row) 
    {
        System.out.print(value + " ");
    }
    System.out.println();
}

4. Типові сценарії застосування зубчастих масивів

Коли зубчастий масив може бути кориснішим за двовимірний?

  • Якщо ви зберігаєте для кожного користувача різну кількість даних: оцінки з предметів, покупки, коментарі тощо.
  • Якщо ваші дані мають трикутну або східчасту структуру (наприклад, для виведення пірамід, трикутників Паскаля тощо).
  • Якщо хочете заощаджувати памʼять: у двовимірному масиві всі рядки фіксованої довжини, а в зубчастому — лише потрібна кількість елементів для кожного рядка.

Приклад із життя: менеджер оцінок студентів

Припустімо, у нас є три студенти, і ось їхні оцінки за різні завдання з математики:

Студент Оцінки
0 5, 4
1 3, 4, 4
2 5

Оголосимо такий масив:

int[][] studentMarks = new int[3][];
studentMarks[0] = new int[] { 5, 4 };         // Перший студент — 2 оцінки
studentMarks[1] = new int[] { 3, 4, 4 };      // Другий студент — 3 оцінки
studentMarks[2] = new int[] { 5 };            // Третій студент — 1 оцінка

Виведемо оцінки кожного студента:

for (int i = 0; i < studentMarks.length; i++) 
{
    System.out.print("Студент " + i + ": ");
    for (int j = 0; j < studentMarks[i].length; j++) 
    {
        System.out.print(studentMarks[i][j] + " ");
    }
    System.out.println();
}

Використання зубчастих масивів із іншими типами

Зубчастим може бути масив чого завгодно: рядків, масивів інших масивів (глибше!), навіть ваших власних об’єктів.

Приклад: масив рядків

String[][] groups = {
    { "Іван", "Петро" },
    { "Марія", "Олексій", "Сергій" },
    { "Василиса" }
};

5. Тривимірні та багатовимірні масиви

І ще один цікавий факт про масиви, про який ви, мабуть, уже здогадуєтеся: якщо можна зробити двовимірний масив, то можна зробити й тривимірний.

Так, можна створити масив будь-якої розмірності. Такі масиви називають багатовимірними.

Як оголошувати багатовимірні масиви

Достатньо просто вказати потрібну кількість розмірів у квадратних дужках:

int[][][] cube = new int[2][3][4]; // 2 «шари», 3 рядки, 4 стовпці
cube[0][1][2] = 99;

Тут у нас тривимірний масив:

  • 2 елементи за першою координатою,
  • 3 — за другою,
  • 4 — за третьою.

Такий масив — це один великий «куб» даних, упакований послідовно.

Перебирання тривимірного масиву

Доступ до елемента здійснюється за всіма індексами одразу:

for (int i = 0; i < cube.length; i++) 
{
    for (int j = 0; j < cube[i].length; j++) 
    {
        for (int k = 0; k < cube[i][j].length; k++) 
        {
            System.out.print(cube[i][j][k] + " ");
        }
        System.out.println();
    }
    System.out.println("---");
}
  • Індекси нумеруються з нуля, як завжди у Java.
  • Усього в такому масиві буде 2 × 3 × 4 = 24 елементи.

Практичні приклади багатовимірних масивів

  • 2D — таблиці, шахові дошки, зображення.
  • 3D — «кубики» у компʼютерній графіці, дані для наукових розрахунків (наприклад, температура в різних точках простору та часу).
  • 4D і вище — рідко використовуються, але трапляються в просунутій математиці, симуляціях, машинному навчанні тощо.

6. Типові помилки під час роботи з багатовимірними масивами

Помилка № 1: Вихід за межі масиву

Найпоширеніша помилка — спроба звернутися до неіснуючого елемента, наприклад:

int[][] arr = new int[2][3];
arr[2][0] = 5; // Помилка! Немає рядка з індексом 2 (є лише 0 і 1)
arr[0][3] = 7; // Помилка! Немає стовпця з індексом 3 (є лише 0, 1, 2)

За такого звернення програма викине виняток ArrayIndexOutOfBoundsException. Завжди перевіряйте, що індекси в допустимих межах: від 0 до length - 1.

Помилка № 2: Неініціалізовані рядки в зубчастому масиві

Якщо створити зубчастий масив і забути ініціалізувати внутрішні масиви, під час звернення буде NullPointerException:

int[][] jagged = new int[3][];
jagged[0][0] = 5; // Помилка! jagged[0] == null

Спочатку треба створити внутрішній масив: jagged[0] = new int[2];

Помилка № 3: Некоректне використання довжини масиву

Плутають matrix.length (кількість рядків) і matrix[0].length (кількість стовпців). Особливо часто — під час копіювання, перебирання або підсумовування за стовпцями.

Помилка № 4: Припущення, що всі рядки однакової довжини

У зубчастих масивах рядки можуть бути різної довжини. Якщо ви пишете matrix[i][j], переконайтеся, що j < matrix[i].length.

Помилка № 5: Плутанина в порядку індексів

Іноді плутають порядок індексів: спочатку йде рядок, а потім стовпець — matrix[рядок][стовпець], а не навпаки.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ