📊 ОАиП. Лекция 39 — Массивы в Java: одномерные и двумерные

📚 Тема лекции: Массивы — фундаментальная структура данных в программировании. На этой лекции мы разберём, что такое массивы, как с ними работать в Java, и научимся решать типичные задачи с одномерными и двумерными массивами.

Преподаватель: Ваш преподаватель ОАиП
Сайт: gadget59.ru

📋 План лекции

  1. Что такое массив и зачем он нужен
  2. Одномерные массивы: объявление и создание
  3. Доступ к элементам массива
  4. Свойство length и перебор массивов
  5. Типичные задачи с одномерными массивами
  6. Двумерные массивы (матрицы)
  7. Доступ к элементам двумерного массива
  8. Перебор элементов двумерного массива
  9. Типичные задачи с двумерными массивами
  10. Типичные ошибки при работе с массивами
  11. Практика: задачи для самостоятельного решения
  12. Итоги и что дальше

🤔 Что такое массив?

Массив (array) — это упорядоченная коллекция элементов одного типа данных, расположенных в памяти компьютера подряд. Каждый элемент массива имеет свой номер, который называется индексом.

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

💡 Важное правило: В Java (и в большинстве языков программирования) индексация массивов начинается с нуля. Это значит, что первый элемент массива имеет индекс 0, второй — индекс 1, третий — индекс 2, и так далее.

🎯 Зачем нужны массивы?

Представьте, что вам нужно хранить оценки 30 студентов. Без массивов вам пришлось бы создавать 30 отдельных переменных:

int student1 = 5;
int student2 = 4;
int student3 = 3;
// ... и так далее 30 раз

Это крайне неудобно! А если студентов 100? А если 1000? С массивами задача решается элегантно:

int[] grades = new int[30]; // Массив из 30 целых чисел
grades[0] = 5;
grades[1] = 4;
grades[2] = 3;
// ... и так далее

Кроме того, массивы позволяют легко перебирать все элементы с помощью циклов, что делает код компактным и эффективным.

📏 Одномерные массивы: объявление

В Java массив — это объект, поэтому для его создания нужно использовать оператор new. Есть несколько способов объявить и создать массив:

Способ 1: Объявление с указанием размера

// Синтаксис: тип_данных[] имя_массива = new тип_данных[размер];
int[] numbers = new int[5]; // Массив из 5 целых чисел
String[] names = new String[10]; // Массив из 10 строк
double[] prices = new double[100]; // Массив из 100 вещественных чисел

При таком способе создания все элементы массива автоматически заполняются значениями по умолчанию:

  • 🔢 Для числовых типов (int, double, float) — значение 0 или 0.0
  • ✅ Для логического типа (boolean) — значение false
  • 📭 Для ссылочных типов (String, объекты) — значение null (пустая ссылка)

📝 Инициализация массива

Способ 2: Объявление с инициализацией

Если вы сразу знаете, какие значения должны быть в массиве, можно заполнить его при создании:

// Синтаксис: тип_данных[] имя_массива = {значение1, значение2, ...};
int[] numbers = {10, 20, 30, 40, 50};
String[] fruits = {"Яблоко", "Банан", "Апельсин"};
boolean[] flags = {true, false, true, true};

В этом случае размер массива определяется автоматически по количеству указанных значений.

💡 Совет: Используйте инициализацию, когда знаете все значения заранее. Используйте создание с размером, когда будете заполнять массив позже (например, в цикле или из файла).

🔍 Доступ к элементам массива

Чтобы получить или изменить значение элемента массива, нужно указать его индекс в квадратных скобках:

int[] numbers = {10, 20, 30, 40, 50};

// Чтение значений
System.out.println(numbers[0]); // Выведет: 10 (первый элемент)
System.out.println(numbers[2]); // Выведет: 30 (третий элемент)
System.out.println(numbers[4]); // Выведет: 50 (пятый элемент)

// Изменение значений
numbers[1] = 99; // Теперь второй элемент равен 99
System.out.println(numbers[1]); // Выведет: 99
⚠️ Типичная ошибка: Попытка обратиться к несуществующему индексу приведёт к ошибке ArrayIndexOutOfBoundsException (исключение выхода за границы массива). Если массив имеет размер 5, допустимые индексы — от 0 до 4. Попытка обратиться к numbers[5] или numbers[-1] вызовет ошибку.

📏 Свойство length

Чтобы узнать количество элементов в массиве, используйте свойство length (длина):

int[] numbers = {10, 20, 30, 40, 50};
System.out.println(numbers.length); // Выведет: 5

String[] names = new String[10];
System.out.println(names.length); // Выведет: 10
💡 Важно: Свойство length — это не метод (не нужно писать скобки), а именно свойство объекта массива. Это отличает его от метода length() у строк.

🔄 Перебор массива: цикл for

Чаще всего массивы используются в связке с циклами. Есть два основных способа перебрать все элементы массива:

Способ 1: Цикл for с индексом

int[] numbers = {10, 20, 30, 40, 50};

// Перебор всех элементов массива
for (int i = 0; i < numbers.length; i++) {
    System.out.println("Элемент с индексом " + i + ": " + numbers[i]);
}

// Выведет:
// Элемент с индексом 0: 10
// Элемент с индексом 1: 20
// Элемент с индексом 2: 30
// Элемент с индексом 3: 40
// Элемент с индексом 4: 50

Этот способ удобен, когда вам нужно знать индекс элемента или изменять значения в массиве.

🔄 Перебор массива: for-each

Способ 2: Цикл for-each (усовершенствованный цикл for)

int[] numbers = {10, 20, 30, 40, 50};

// Перебор всех элементов массива без использования индекса
for (int number : numbers) {
    System.out.println("Значение: " + number);
}

// Выведет:
// Значение: 10
// Значение: 20
// Значение: 30
// Значение: 40
// Значение: 50

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

🧮 Задача 1: Сумма элементов

Найти сумму всех элементов массива:

int[] numbers = {10, 20, 30, 40, 50};
int sum = 0; // Переменная для хранения суммы

for (int number : numbers) {
    sum += number; // Прибавляем каждый элемент к сумме
}

System.out.println("Сумма всех элементов: " + sum); // Выведет: 150
💡 Алгоритм: Создаём переменную-аккумулятор (sum), инициализируем её нулём, затем в цикле прибавляем каждый элемент массива к этой переменной.

📈 Задача 2: Максимальный элемент

Найти максимальный элемент массива:

int[] numbers = {10, 50, 30, 20, 40};
int max = numbers[0]; // Предполагаем, что первый элемент — максимальный

for (int i = 1; i < numbers.length; i++) {
    if (numbers[i] > max) { // Если текущий элемент больше max
        max = numbers[i]; // Обновляем max
    }
}

System.out.println("Максимальный элемент: " + max); // Выведет: 50
💡 Важно: Всегда инициализируйте переменную max первым элементом массива (или минимально возможным значением), а не нулём! Иначе, если все элементы отрицательные, алгоритм будет работать неправильно.

📉 Задача 3: Минимальный элемент

Найти минимальный элемент массива:

int[] numbers = {10, 50, 30, 20, 40};
int min = numbers[0]; // Предполагаем, что первый элемент — минимальный

for (int i = 1; i < numbers.length; i++) {
    if (numbers[i] < min) { // Если текущий элемент меньше min
        min = numbers[i]; // Обновляем min
    }
}

System.out.println("Минимальный элемент: " + min); // Выведет: 10

Алгоритм полностью аналогичен поиску максимума, только сравниваем с оператором < вместо >.

🔢 Задача 4: Подсчёт по условию

Подсчитать количество элементов, удовлетворяющих условию:

int[] grades = {5, 4, 3, 5, 2, 4, 5, 3};
int countExcellent = 0; // Счётчик пятёрок

for (int grade : grades) {
    if (grade == 5) { // Если оценка равна 5
        countExcellent++; // Увеличиваем счётчик
    }
}

System.out.println("Количество пятёрок: " + countExcellent); // Выведет: 3
💡 Паттерн: Это классический паттерн "счётчик". Создаём переменную-счётчик, инициализируем нулём, и в цикле увеличиваем её на 1 при выполнении условия.

🎲 Задача 5: Случайные числа

Заполнить массив случайными числами:

import java.util.Random;

int[] numbers = new int[10]; // Создаём массив из 10 элементов
Random random = new Random(); // Создаём генератор случайных чисел

for (int i = 0; i < numbers.length; i++) {
    numbers[i] = random.nextInt(100); // Случайное число от 0 до 99
}

// Выводим заполненный массив
System.out.print("Массив: ");
for (int number : numbers) {
    System.out.print(number + " ");
}
// Пример вывода: Массив: 45 12 78 3 67 89 23 56 91 34
💡 Метод nextInt(n): Возвращает случайное целое число от 0 (включительно) до n (не включая). То есть nextInt(100) даёт числа от 0 до 99.

📊 Двумерные массивы (матрицы)

Двумерный массив — это массив, элементами которого являются другие массивы. Проще говоря, это таблица, состоящая из строк и столбцов. В математике такие таблицы называются матрицами.

Представьте себе таблицу Excel или шахматную доску. Каждая ячейка имеет две координаты: номер строки и номер столбца. Двумерный массив работает точно так же.

💡 Аналогия: Если одномерный массив — это список (одна линия), то двумерный массив — это таблица (строки и столбцы).

📏 Объявление двумерного массива

Способ 1: Указание размеров

// Синтаксис: тип_данных[][] имя_массива = new тип_данных[строки][столбцы];
int[][] matrix = new int[3][4]; // Матрица 3 строки × 4 столбца

Это создаст матрицу размером 3×4 (3 строки и 4 столбца), заполненную нулями:

Столбец 0 Столбец 1 Столбец 2 Столбец 3
Строка 0 0 0 0 0
Строка 1 0 0 0 0
Строка 2 0 0 0 0

📝 Инициализация двумерного массива

Способ 2: Инициализация значениями

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

Это создаст матрицу 3×3:

Столбец 0 Столбец 1 Столбец 2
Строка 0 1 2 3
Строка 1 4 5 6
Строка 2 7 8 9

🔍 Доступ к элементам двумерного массива

Чтобы получить доступ к элементу двумерного массива, нужно указать два индекса: сначала индекс строки, затем индекс столбца.

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

// Чтение значений
System.out.println(matrix[0][0]); // Выведет: 1 (строка 0, столбец 0)
System.out.println(matrix[1][2]); // Выведет: 6 (строка 1, столбец 2)
System.out.println(matrix[2][1]); // Выведет: 8 (строка 2, столбец 1)

// Изменение значений
matrix[0][1] = 99; // Изменяем элемент в строке 0, столбце 1
System.out.println(matrix[0][1]); // Выведет: 99

📏 Размеры двумерного массива

Для двумерного массива свойство length работает немного иначе:

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

System.out.println(matrix.length); // Выведет: 3 (количество строк)
System.out.println(matrix[0].length); // Выведет: 3 (количество столбцов в строке 0)
💡 Важно: matrix.length возвращает количество строк. Чтобы получить количество столбцов, нужно обратиться к длине любой строки: matrix[0].length.

🔄 Перебор двумерного массива: for

Для перебора двумерного массива нужны два вложенных цикла: один для строк, другой для столбцов.

Способ 1: С использованием индексов

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(); // Переход на новую строку после каждой строки матрицы
}

// Выведет:
// 1 2 3 
// 4 5 6 
// 7 8 9

🔄 Перебор двумерного массива: for-each

Способ 2: С использованием for-each

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

// Перебор всех элементов матрицы без индексов
for (int[] row : matrix) { // row — это одномерный массив (строка)
    for (int element : row) { // element — это отдельный элемент
        System.out.print(element + " ");
    }
    System.out.println();
}

// Выведет:
// 1 2 3 
// 4 5 6 
// 7 8 9
💡 Как это работает: Внешний цикл перебирает строки (каждая строка — это массив int[]), внутренний цикл перебирает элементы внутри каждой строки.

🧮 Задача: Сумма элементов матрицы

Найти сумму всех элементов матрицы:

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

int sum = 0;

for (int[] row : matrix) {
    for (int element : row) {
        sum += element;
    }
}

System.out.println("Сумма всех элементов: " + sum); // Выведет: 45

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

📐 Задача: Главная диагональ

Найти сумму элементов главной диагонали:

Главная диагональ — это элементы матрицы, у которых индекс строки равен индексу столбца (то есть элементы matrix[0][0], matrix[1][1], matrix[2][2] и так далее).

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

int diagonalSum = 0;

for (int i = 0; i < matrix.length; i++) {
    diagonalSum += matrix[i][i]; // Берём элементы, где индекс строки = индекс столбца
}

System.out.println("Сумма главной диагонали: " + diagonalSum); // Выведет: 15 (1 + 5 + 9)

🔄 Задача: Транспонирование матрицы

Транспонирование — это операция, при которой строки матрицы становятся столбцами, а столбцы — строками.

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

// Создаём новую матрицу для транспонированного результата
int[][] transposed = new int[matrix[0].length][matrix.length];

for (int i = 0; i < matrix.length; i++) {
    for (int j = 0; j < matrix[i].length; j++) {
        transposed[j][i] = matrix[i][j]; // Меняем индексы местами
    }
}

// Выводим результат
System.out.println("Транспонированная матрица:");
for (int[] row : transposed) {
    for (int element : row) {
        System.out.print(element + " ");
    }
    System.out.println();
}

// Выведет:
// 1 4 
// 2 5 
// 3 6

⚠️ Типичные ошибки при работе с массивами

  1. Выход за границы массива: Попытка обратиться к индексу, который не существует (например, array[10] для массива размером 10).
  2. Забыть, что индексация начинается с 0: Первый элемент — это array[0], а не array[1].
  3. Неправильное использование свойства length: Для двумерных массивов matrix.length возвращает количество строк, а не общее количество элементов.
  4. Изменение массива в цикле for-each: Цикл for-each не позволяет изменять элементы массива, только читать их.
  5. Инициализация max/min нулём: Если ищете минимум/максимум, инициализируйте переменную первым элементом массива, а не нулём.

💪 Задачи для самостоятельного решения

  1. Напишите программу, которая находит среднее арифметическое элементов одномерного массива.
  2. Напишите программу, которая переворачивает одномерный массив (первый элемент становится последним, второй — предпоследним и так далее).
  3. Напишите программу, которая находит сумму элементов побочной диагонали квадратной матрицы (диагональ идёт из правого верхнего угла в левый нижний).
  4. Напишите программу, которая находит максимальный элемент в каждой строке двумерного массива.
  5. Напишите программу, которая проверяет, является ли двумерный массив симметричным относительно главной диагонали (то есть matrix[i][j] == matrix[j][i] для всех i и j).

✅ Итоги лекции

  • Массив — это упорядоченная коллекция элементов одного типа данных.
  • Индексация массивов в Java начинается с нуля.
  • Для доступа к элементу массива используется синтаксис array[index].
  • Свойство length возвращает количество элементов в массиве.
  • Для перебора массивов используются циклы for или for-each.
  • Двумерный массив — это массив массивов, представляющий собой таблицу (матрицу).
  • Для доступа к элементу двумерного массива используются два индекса: matrix[row][column].

🚀 Что дальше?

На следующих лекциях мы продолжим изучать структуры данных:

  • 📦 Множества (Set) — коллекции без дубликатов
  • 🔄 Рекурсия — функции, вызывающие сами себя
  • 📁 Файлы прямого доступа — работа с файлами на низком уровне
  • 🎯 Коллекции Java — ArrayList, HashMap и другие
🎉 Поздравляю! Вы освоили одну из самых важных тем в программировании. Массивы — это фундамент, на котором строится всё остальное. Практикуйтесь, решайте задачи, и вы будете работать с массивами как профессионал!

📚 Спасибо за внимание!

Вопросы?

← Вернуться на главную страницу

1 / 30