Многомерные массивы

🔥 🚀 Важно для всех, кто работает с Java! 🔥
На JavaRocks ты найдешь уникальные туториалы, практические задачи и редкие книги, которых не найти в свободном доступе. Присоединяйся к нашему Telegram-каналу JavaRocks — стань частью профессионального сообщества!

Всем привет! Сегодня мы подробно изучим многомерные массивы в Java.

Представьте шахматную доску. Мы можем взять монетку и положить на любую клеточку. Чтобы определить её местоположение, нужно знать номер как строки, так и столбца. Это и есть двумерный массив 🙂

Определение

Многомерные массивы – это массивы, в которых хранятся другие массивы. Представьте себе многоквартирный дом: зная номер этажа, вы можете попасть в нужный коридор, а номер квартиры укажет на нужную дверь. Именно так и работают массивы массивов в Java.

Возьмем двумерный массив:

int[][] grid = {
    {1, 2, 3},  // строка 0
    {4, 5, 6},  // строка 1
    {7, 8, 9}   // строка 2
};

int num = grid[1][1];  // на пересечении 1 строки и 1 столбца - 5
Run Code

Перед нами сетка 3×3; два индекса точно определяют искомое местоположение. Все очень просто: данные организуются в нескольких измерениях, а не просто в виде линейной последовательности чисел.

Объявление многомерных массивов

Существует два способа:

int[][] matrix;  // нагляднее показывает, что создаётся вложенная структура
int matrix[][];  // способ тоже рабочий, но менее элегантный
Run Code

Способы инициализации

1. Пустая сетка, готовая к заполнению

int[][] grid = new int[3][4];  // 3 строки и 4 столбца заполнены нулями

2. Инициализация сразу с данными

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

3. Построчное заполнение

double[][] temps = new double[2][3];
temps[0][0] = 78.5; 
temps[0][1] = 80.1; 
Run Code

Для быстрого тестирования можно выбрать 2-ой вариант. Для реальных приложений, где данные поступают постепенно, лучше использовать 1-ый и 3-ий способы.

Операции над двумерными массивами

Перебор элементов

Нужно обработать каждый элемент? На помощь приходят вложенные циклы:

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

for (int i = 0; i < matrix.length; i++) {
    for (int j = 0; j < matrix[i].length; j++) {
        System.out.print(matrix[i][j] + " ");
    }
    System.out.println();
}
Run Code

Вывод:

1 2 3
4 5 6
7 8 9

Как вариант – можно использовать цикл for-each:

for (int[] row : matrix) {
    for (int num : row) {
        System.out.print(num + " ");
    }
    System.out.println();
}
Run Code

Пример № 1: доска для игры в крестики-нолики

public class TicTacToeFun {
    public static void main(String[] args) {
        int[][] board = new int[3][3];  // 0 = прочерк, 1 = X, 2 = O

        board[0][0] = 1;  // X верхний левый угол
        board[1][1] = 2;  // O центр
        board[0][1] = 1;  // X центр верхнего ряда

        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (board[i][j] == 0) System.out.print(" - ");
                else if (board[i][j] == 1) System.out.print(" X ");
                else System.out.print(" O ");
            }
            System.out.println();
        }
    }
}
Run Code

Вывод:

X  X  -
-  O  -
-  -  -

Пример №2: сложение матриц

public class MatrixMath {
    public static void main(String[] args) {
        int[][] a = {{1, 2, 3}, {4, 5, 6}};
        int[][] b = {{7, 8, 9}, {10, 11, 12}};

        int[][] result = new int[a.length][a[0].length];

        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < a[i].length; j++) {
                result[i][j] = a[i][j] + b[i][j];
            }
        }

        for (int[] row : result) {
            for (int val : row) {
                System.out.print(val + " ");
            }
            System.out.println();
        }
    }
}
Run Code

Вывод:

8 10 12
14 16 18

Трехмерные массивы

Иногда вам нужно нечто большее, чем двумерный массив; например, массив трехмерный. Чтобы понять, что это, достаточно представить многоуровневую парковку с несколькими этажами

int[][][] stack = new int[2][3][4];  // 2 "этажа", 3 строки и 4 столбца
stack[0][1][2] = 42;

int[][][] cube = {
    {{1, 2}, {3, 4}, {5, 6}},
    {{7, 8}, {9, 10}, {11, 12}}
};
Run Code

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

public class GradeBoss {
    public static void main(String[] args) {
        double[][][] grades = {
            {{88.5, 92.0, 79.5}, {90.0, 85.5, 83.0}},  // Оценки первого студента
            {{77.0, 85.0, 91.0}, {82.5, 89.0, 93.5}}   // Оценки второго студента
        };

        double sum = 0;
        for (int sub = 0; sub < grades[0][0].length; sub++) {
            sum += grades[0][0][sub];
        }
        double avg = sum / grades[0][0].length;
        System.out.println("Student 1, Semester 1 avg: " + avg);
    }
}
Run Code

Вывод:

Student 1, Semester 1 avg: 86.66666666666667

Рваные массивы

Одна из самых крутых функций Java – возможность создавать рваные массивы (многомерные массивы, в которых каждая строка может иметь разную длину). Такая опция очень полезна для нерегулярных данных!

// Создаем рваный массив
int[][] jaggedArray = new int[3][]; // 3 строки неопределенной длины

// Инициализация каждой строки с учетом разных длин
jaggedArray[0] = new int[4]; // У первой строки - 4 элемента
jaggedArray[1] = new int[2]; // У второй - 2 элемента
jaggedArray[2] = new int[5]; // У третьей - 5 элементов

// Альтернативный вариант: инициализация с непосредственным заполнением 
int[][] triangle = {
 {1},
 {2, 3},
 {4, 5, 6},
 {7, 8, 9, 10}
};
Run Code

Пример: узор в виде треугольника из чисел

public class TrianglePattern {
 public static void main(String[] args) {
 int rows = 5;
 int[][] triangle = new int[rows][];

 // Создаём рваный массив, длина строк которого постепенно увеличивается на 1
 for (int i = 0; i < rows; i++) {
 triangle[i] = new int[i + 1];

 // Заполнение в соответствии с номером строки
 for (int j = 0; j < triangle[i].length; j++) {
 triangle[i][j] = i + 1;
 }
 }

 // Вывод треугольника
 for (int[] row : triangle) {
 for (int num : row) {
 System.out.print(num + " ");
 }
 System.out.println();
 }
 }
}
Run Code

Вывод:

1
2 2
3 3 3
4 4 4 4
5 5 5 5 5

Практические примеры использования многомерных массивов

1. Разработка игр

  • Доски для шахмат/шашек (сетка 8×8)
  • Головоломки типа Судоку (сетка 9×9)
  • Карты-плитки в 2D-играх
  • Системы обнаружения столкновений

2. Математические операции

  • Матричные операции (сложение, умножение)
  • Представления графов
  • Решение систем уравнений

3. Анализ данных

  • Табличные данные
  • Тепловые карты
  • Статистические таблицы

Преимущества и ограничения

Преимущества

  • Прямой доступ к любому элементу
  • Эффективность использования памяти (особенно для рваных массивов)
  • Многомерные массивы интуитивно понятны для работы с сеточными структурами

Ограничения

  • Фиксированный размер: сложно изменить размер после создания
  • Нединамичны – в отличие от ArrayList и других коллекций
  • Потенциально расточительны: обычные массивы выделяют место для всех ячеек, даже если они не используются

Часто задаваемые вопросы

Как заполнить массив случайными числами?

Используйте Random в цикле. Можете провести эксперимент: в примере с треугольником поменять i + 1 на rand.nextInt().

Массивы vs ArrayList?

Массивы используются при работе с сетками фиксированного размера, а ArrayList – если предполагаются изменения в структуре данных (если надо будет что-то добавлять/убирать).

Бывают ли массивы более трех измерений?

Да, но работать с ними сложно, а на практике и вовсе редко нужно.

Перевод статьи «Java Multidimensional Array».

Хотите знать больше? Рекомендуем полезную статью «Массивы в Java»

Оставьте комментарий

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

Прокрутить вверх